home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ccdl151s.zip / SOURCE / GEXPR386.C < prev    next >
C/C++ Source or Header  |  1997-06-14  |  88KB  |  2,723 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. #include        <stdio.h>
  23. #include        "expr.h"
  24. #include        "c.h"
  25. #include        "gen386.h"
  26. #include                 "diag.h"
  27.  
  28. /*
  29.  *      this module contains all of the code generation routines
  30.  *      for evaluating expressions and conditions.
  31.  */
  32. extern int stdinttype,stdunstype,stdintsize, stdldoublesize,stdaddrsize;
  33. extern int stackadd,stackmod;
  34. extern int prm_largedata, prm_linkreg;
  35. extern AMODE     push[], pop[];
  36. extern int prm_68020;
  37. extern long framedepth, stackdepth;
  38. extern int regs[3];
  39. extern long nextlabel;
  40. extern long lc_maxauto;
  41. extern char regstack[],rsold[],rsodepth,rsdepth;
  42. AMODE freg0[] = { { am_freg, 0 } };
  43. AMODE sreg[] = { { am_dreg,4 } };
  44.  
  45. long bittab[32] = { 1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff,
  46.             0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
  47.             0x1ffffL,0x3ffffL,0x7ffffL,0xfffffL,0x1fffffL,0x3fffffL,0x7fffffL,0xffffffL,
  48.             0x1ffffffL,0x3ffffffL,0x7ffffffL,0xfffffffL,0x1fffffffL,0x3fffffffL,0x7fffffffL,0xffffffffL
  49. };
  50.  
  51. void gen_f10code(int op, int size, AMODE *ap1, AMODE *ap2)
  52. {
  53.     if (size != 10) 
  54.         gen_code(op,size,ap1,ap2);
  55.     else {
  56.         gen_code(op_fld,size,ap1,ap2);
  57.         gen_code(op,size,0,0);
  58.     }
  59. }
  60. int chksize(int lsize, int rsize)
  61. {
  62.     int l,r;
  63.     l = lsize;
  64.     r = rsize;
  65.     if (l < 0) l = - l;
  66.     if (r < 0) r = - r;
  67.     return(l > r);
  68. }
  69. AMODE *fstack(void)
  70. {
  71.     AMODE *ap = xalloc(sizeof(AMODE));
  72.     ap->mode = am_freg;
  73.     ap->preg = 0;
  74.     ap->sreg = 0;
  75.     ap->offset = 0;
  76.     ap->tempflag = TRUE;
  77.     return(ap);
  78. }
  79. AMODE        *make_muldivval(AMODE *ap)
  80. {
  81.             int temp;
  82.             AMODE *ap1 = make_label(temp = nextlabel++);
  83.             queue_muldivval(temp,ap->offset->v.i);
  84.             ap1->mode = am_direct;
  85.             return(ap1);
  86. }
  87. void make_floatconst(AMODE *ap, int size)
  88. {
  89.     int temp;
  90.     AMODE *ap1 = make_label(temp = nextlabel++);
  91.     if (isintconst(ap->offset->nodetype))
  92.         ap->offset->v.f = ap->offset->v.i;
  93.     queue_floatval(temp,ap->offset->v.f,size);
  94.     ap->mode = am_direct;
  95.     ap->length = 8;
  96.     ap->offset = ap1->offset;
  97. }
  98. AMODE    *make_label(int lab)
  99. /*
  100.  *      construct a reference node for an internal label number.
  101.  */
  102. {       ENODE    *lnode;
  103.         AMODE    *ap;
  104.         lnode = xalloc(sizeof(ENODE));
  105.         lnode->nodetype = en_labcon;
  106.         lnode->v.i = lab;
  107.         ap = xalloc(sizeof(AMODE));
  108.         ap->mode = am_immed;
  109.         ap->offset = lnode;
  110.         return ap;
  111. }
  112.  
  113. AMODE    *make_immed(long i)
  114. /*
  115.  *      make a node to reference an immediate value i.
  116.  */
  117. {       AMODE    *ap;
  118.         ENODE    *ep;
  119.         ep = xalloc(sizeof(ENODE));
  120.         ep->nodetype = en_icon;
  121.         ep->v.i = i;
  122.         ap = xalloc(sizeof(AMODE));
  123.         ap->mode = am_immed;
  124.         ap->offset = ep;
  125.         return ap;
  126. }
  127. AMODE    *make_immedt(long i, int size)
  128. /*
  129.  *      make a node to reference an immediate value i.
  130.  */
  131. {
  132.                 switch (size) {
  133.                     case 1:
  134.                     case -1:
  135.                         i &= 0xff;
  136.                         break;
  137.                     case 2:
  138.                     case -2:
  139.                         i &= 0xffff;
  140.                         break;
  141.                 }
  142.                 return make_immed(i);
  143. }
  144.  
  145. AMODE    *make_offset(ENODE *node)
  146. /*
  147.  *      make a direct reference to a node.
  148.  */
  149. {       AMODE    *ap;
  150.         ap = xalloc(sizeof(AMODE));
  151.         ap->mode = am_direct;
  152.         ap->offset = node;
  153.         return ap;
  154. }
  155. AMODE *make_stack(int number)
  156. {
  157.     AMODE *ap = xalloc(sizeof(AMODE));        
  158.     ENODE *ep = xalloc(sizeof(ENODE));
  159.     ep->nodetype = en_icon;
  160.     ep->v.i = -number;
  161.     ap->mode = am_indisp;
  162.     ap->preg = ESP;
  163.     ap->offset = ep;
  164.     return(ap);
  165. }
  166. void make_legal(AMODE *ap,int flags,int size)
  167. /*
  168.  *      make_legal will coerce the addressing mode in ap1 into a
  169.  *      mode that is satisfactory for the flag word.
  170.  */
  171. {       AMODE    *ap2,*ap1;
  172.         if( ((flags & F_VOL) == 0) || ap->tempflag )
  173.                 {
  174.                 switch( ap->mode )
  175.                         {
  176.                                                 case am_freg:
  177.                                                                 if (flags & F_FREG && size > 4)
  178.                                                                         return;
  179.                                                                 break;
  180.                         case am_immed:
  181.                                                                 if (size > 4) {
  182.                                                                     make_floatconst(ap,size);
  183.                                                   if (flags & F_MEM)
  184.                                                                         return;
  185.                                                                 }
  186.                                                                 else
  187.                                     if( flags & F_IMMED )
  188.                                         return;         /* mode ok */
  189.                                                                 
  190.                                 break;
  191.                         case am_dreg:
  192.                                 if( flags & F_DREG) {
  193.                                   return;
  194.                                                                 }
  195.                                 break;
  196.                                                 case am_indisp: case am_indispscale: 
  197.                                                 case am_direct:
  198.                                                                 if (flags & F_INDX)
  199.                                                                     return;
  200.                                 if( flags & F_MEM)
  201.                                         return;
  202.                                 break;
  203.                         }
  204.                 }
  205.                 if (!(flags & F_DREG)) {
  206.                     if (flags & F_FREG && ap->mode != am_freg && !(flags & F_MEM)) {
  207.                         freeop(ap);
  208.                         if (size <=4) 
  209.                             if (size == 1 || size == -1) {
  210.                                 ap1 = temp_data();
  211.                                 if (size < 0)
  212.                                     gen_code2(op_movsx,4,1,ap1,ap);
  213.                                 else
  214.                                     gen_code2(op_movzx,4,1,ap1,ap);
  215.                                 gen_code(op_push,4,ap1,0);
  216.                                 gen_code(op_fild,2,make_stack(0),0);
  217.                                 gen_code(op_add,4,sreg,make_immed(4));
  218.                                 freeop(ap1);
  219.                             }
  220.                             else
  221.                                 gen_code(op_fild,size,ap,0);
  222.                         else
  223.                             gen_code(op_fld,size,ap,0);
  224.                         ap->mode = am_freg;
  225.                         ap->preg = 0;
  226.                         return;
  227.                     }
  228.                 }
  229.                 else if (size > 4) {
  230.                     freeop(ap);
  231.                     gen_code(op_fld,size,ap,0);
  232.                     if (flags & F_FREG) {
  233.                         ap->mode = am_freg;
  234.                         ap->preg = 0;
  235.                         return;
  236.                     }
  237.                     else {
  238.                         gen_code(op_push,4,makedreg(3),0);
  239.                         gen_code(op_fistp,4,make_stack(0),0);
  240.                         ap1 = temp_data();
  241.                         gen_code(op_pop,4,ap1,make_stack(0));
  242.                         ap->mode = ap1->mode;
  243.                         ap->preg = ap1->preg;
  244.                         return;
  245.                     }
  246.                 }
  247.         if( size == -1 )
  248.                 {
  249.                 freeop(ap);
  250.                 ap2 = temp_data();
  251.                                 if (ap->mode == am_immed)
  252.                     gen_code(op_mov,1,ap2,ap);
  253.                                 else if (ap->mode == am_dreg && ap->preg > 3)
  254.                     gen_code(op_mov,4,ap2,ap);
  255.                                 else
  256.                     gen_code2(op_movsx,4,1,ap2,ap);
  257.                 ap->mode = ap2->mode;
  258.                 ap->preg = ap2->preg;
  259.                                 ap->tempflag = TRUE;
  260.                 size = -2;
  261.                 }
  262.                 
  263.         else if( size == 1 )
  264.                 {
  265.                 freeop(ap);
  266.                 ap2 = temp_data();
  267.                                 if (ap->mode == am_immed)
  268.                     gen_code(op_mov,1,ap2,ap);
  269.                                 else if (ap->mode == am_dreg && ap->preg > 3)
  270.                     gen_code(op_mov,4,ap2,ap);
  271.                                 else
  272.                     gen_code2(op_movzx,4,1,ap2,ap);
  273.                 ap->mode = ap2->mode;
  274.                 ap->preg = ap2->preg;
  275.                                 ap->tempflag = TRUE;
  276.                 size = 2;
  277.                 }
  278.         else if( size == -2 )
  279.                 {
  280.                 freeop(ap);
  281.                 ap2 = temp_data();
  282.                                 if (ap->mode == am_immed)
  283.                     gen_code(op_mov,2,ap2,ap);
  284.                                 else if (ap->mode == am_dreg && ap->preg > 3)
  285.                     gen_code(op_mov,4,ap2,ap);
  286.                                 else
  287.                     gen_code2(op_movsx,4,2,ap2,ap);
  288.                 ap->mode = ap2->mode;
  289.                 ap->preg = ap2->preg;
  290.                                 ap->tempflag = TRUE;
  291.                 size = -4;
  292.                 }
  293.                 
  294.         else if( size == 2 )
  295.                 {
  296.                 freeop(ap);
  297.                 ap2 = temp_data();
  298.                                 if (ap->mode == am_immed)
  299.                     gen_code(op_mov,2,ap2,ap);
  300.                                 else if (ap->mode == am_dreg && ap->preg > 3)
  301.                     gen_code(op_mov,4,ap2,ap);
  302.                                 else
  303.                     gen_code2(op_movzx,4,2,ap2,ap);
  304.                 ap->mode = ap2->mode;
  305.                 ap->preg = ap2->preg;
  306.                                 ap->tempflag = TRUE;
  307.                 size = 4;
  308.                 }
  309.                 else if (size == 4 || size == -4) {
  310.             freeop(ap);
  311.             ap2 = temp_data();
  312.             gen_code(op_mov,size,ap2,ap);
  313.             ap->mode = am_dreg;
  314.             ap->preg = ap2->preg;
  315.             ap->tempflag = 1;
  316.                 }
  317. }
  318. void bit_legal(AMODE *ap,ENODE *node, int size)
  319. {
  320.     if (node->bits != -1) {
  321.             make_legal(ap,F_DREG | F_VOL,size);
  322.             if (node->startbit)
  323.                 gen_code(op_shr,size,ap,make_immed(node->startbit));
  324.             gen_code(op_and,4,ap,make_immed(bittab[node->bits-1]));
  325.     }
  326. }
  327. AMODE *get_bitval(AMODE *ap,ENODE *node, int size)
  328. {
  329.     AMODE *ap1 = temp_data();
  330.     ap1->tempflag = TRUE;
  331.         gen_code(op_mov,size,ap1,ap);
  332.         if (node->startbit)
  333.             gen_code(op_shr,size,ap1,make_immed(node->startbit));
  334.         gen_code(op_and,4,ap1,make_immed(bittab[node->bits-1]));
  335.         return ap1;
  336. }
  337. void bit_move(AMODE *ap2, AMODE *ap1, ENODE *node, int flags, int sizein, int sizeout)
  338. {
  339.         gen_code(op_and,sizeout,ap2,make_immed(~(bittab[node->bits-1]<<node->startbit)));
  340.         if (ap1->mode == am_immed) {
  341.             ap1->offset->v.i &= bittab[node->bits-1];
  342.             if (ap1->offset->v.i) {
  343.                 ap1->offset->v.i <<= node->startbit;
  344.                 gen_code(op_or,sizeout,ap2,ap1);
  345.                 if (!(flags & F_NOVALUE)) {
  346.                     make_legal(ap2,flags,sizeout);
  347.                     ap1->offset->v.i >>= node->startbit;
  348.                     gen_code(op_mov,sizeout,ap2,ap1);
  349.                 }
  350.             }
  351.         }
  352.         else {
  353.             make_legal(ap1,F_DREG | F_VOL,sizein);
  354.             gen_code(op_and,sizein,ap1,make_immed(bittab[node->bits-1]));
  355.             if (node->startbit)
  356.                 gen_code(op_shl,sizein,ap1,make_immed(node->startbit));
  357.             gen_code(op_or,sizeout,ap2,ap1);
  358.             if (!(flags & F_NOVALUE)) {
  359.                 if (node->startbit)
  360.                     gen_code(op_shr,sizein,ap1,make_immed(node->startbit));
  361.             }
  362.         }
  363. }
  364. void do_extend(AMODE *ap,int isize,int osize,int flags)
  365. /*
  366.  *      if isize is not equal to osize then the operand ap will be
  367.  *      loaded into a register (if not already) and if osize is
  368.  *      greater than isize it will be extended to match.
  369.  */
  370. {                AMODE *ap2;
  371.                 if (isize == 0)
  372.                     return;
  373.            if( isize == osize || isize == -osize)
  374.                 return;
  375.         if( ap->mode != am_dreg && osize <=4) {
  376.                                     if (flags & F_DEST)
  377.                         make_legal(ap,flags,isize);
  378.                                     else
  379.                         make_legal(ap,F_DREG | F_FREG,isize);
  380.                                     if (flags & F_DEST)
  381.                                         return;
  382.                                     if (chksize(osize,isize))
  383.                                         return;
  384.                 }
  385.                 switch(isize)
  386.                                 {
  387. doextend:
  388.                                 case -1:
  389.                                 case 1:
  390.                 case -2:
  391.                                 case 2:
  392.                                                 if (osize < isize) {
  393.                                                         gen_code2(op_movsx,osize,isize,ap,ap);
  394.                                                 }
  395.                                                 else if (osize <=4 && osize > isize) {
  396.                                                         gen_code2(op_movzx,osize,isize,ap,ap);
  397.                                                 }
  398.                                 case 4:
  399.                                 case -4:
  400. do4:
  401.                                                 if (osize <= 4)
  402.                                                     return;
  403.                                                 else {
  404.                                                     if (ap->mode != am_freg) {
  405.                                                         do_extend(ap,isize,4,F_ALL | F_VOL);
  406.                                                         ap2 = make_stack(0);
  407.                                                         gen_code(op_push,4,ap,0);
  408.                                                         freeop(ap);
  409.                                                         gen_codef(op_fild,4,ap2,0);
  410.                                                         gen_code(op_add,4,sreg,make_immed(4));
  411.                                                         freeop(ap);
  412.                                                     }
  413.                                                     ap->mode = am_freg;
  414.                                                     ap->preg = 0;
  415.                                                     ap->tempflag = TRUE;
  416.                                                 }
  417.                                                 break;
  418.                                 case 6:
  419.                                 case 8:
  420.                                                 if (osize > isize) {
  421.                                                     if (ap->mode != am_freg) {
  422.                                                         gen_codef(op_fld,osize,ap,0);    
  423.                                                         freeop(ap);
  424.                                                         ap->mode = am_freg;
  425.                                                         ap->preg = 0;
  426.                                                         ap->tempflag = TRUE;
  427.                                                     }
  428.                                                     return;
  429.                                                 }
  430.                                                 
  431.                                 case 10: 
  432.                                                 if (ap->mode != am_freg) {
  433.                                                     freeop(ap);
  434.                                                     gen_codef(op_fld,isize,ap,0);
  435.                                                     ap->mode = am_freg;
  436.                                                     ap->preg = 0;
  437.                                                     ap->tempflag = TRUE;
  438.                                                 }
  439.                                                 switch(osize) {
  440.                                                     case 1:
  441.                                                     case -1:
  442.                                                     case 2:
  443.                                                     case -2:
  444.                                                     case 4:
  445.                                                     case -4:
  446.                                                         freeop(ap);
  447.                                                         ap2 = temp_data();
  448.                                                         ap->mode = ap2->mode;
  449.                                                         ap->preg = ap2->preg;
  450.                                                         gen_code(op_push,4,makedreg(3),0);
  451.                                                         gen_codef(op_fistp,4,ap2 = make_stack(0),0);
  452.                                                         gen_codef(op_fwait,0,0,0);
  453.                                                         gen_code(op_mov,osize,ap,ap2);
  454.                                                         gen_code(op_add,4,sreg,make_immed(4));
  455.                                                         goto doextend;
  456.                                                     case 6:
  457.                                                     case 8:
  458.                                                         break;
  459.                                                 }
  460.                 }
  461. }
  462.  
  463. int     isshort(ENODE *node)
  464. /*
  465.  *      return true if the node passed can be generated as a short
  466.  *      offset.
  467.  */
  468. {       return (isintconst(node->nodetype) &&
  469.                 (node->v.i >= -32768L && node->v.i <= 32767L));
  470. }
  471.  
  472. int     isbyte(ENODE *node)
  473. /*
  474.  *      return true if the node passed can be evaluated as a byte
  475.  *      offset.
  476.  */
  477. {       return isintconst(node->nodetype) &&
  478.                 (-128 <= node->v.i && node->v.i <= 127);
  479. }
  480.  
  481. AMODE    *gen_index(ENODE *node)
  482. /*
  483.  *      generate code to evaluate an index node (^+) and return
  484.  *      the addressing mode of the result. This routine takes no
  485.  *      flags since it always returns either am_ind or am_indx.
  486.  */
  487. {       AMODE    *ap1,*ap2, *ap, *ap3;
  488.                 ENODE node2;
  489.                 int scale;
  490.  
  491.                 switch (node->v.p[0]->nodetype) {
  492.                     case en_icon:
  493.                         ap1 = gen_expr(node->v.p[0],F_IMMED,4);
  494.                         break;
  495.                     case en_lsh:
  496.                         if ((scale = node->v.p[0]->v.p[1]->v.i) < 4 && scale) {
  497.                             ap1 = gen_expr(node->v.p[0]->v.p[0],F_IMMED | F_DREG,4);
  498.                             if (ap1->mode == am_immed) {
  499.                                 while (--scale)
  500.                                     ap1->offset->v.i <<=1;
  501.                             }
  502.                             else {
  503.                                 ap1->mode = am_indispscale;
  504.                                 ap1->sreg = ap1->preg;
  505.                                 ap1->preg = -1;
  506.                                 ap1->scale = scale;
  507.                                 ap1->offset = makenode(en_icon,0,0);
  508.                             }
  509.                             break;
  510.                         }
  511.                     default:
  512.                         mark();
  513.                         ap1 = gen_deref(node,F_MEM | F_DREG,4);
  514.                         switch (ap1->mode) {
  515.                             default:
  516.                                 rsold[rsodepth-1] = rsdepth;
  517.                                 break;
  518.                             case am_indispscale:
  519.                                 if (ap1->sreg >=0 && ap1->preg >= 0) {
  520.                                     int t = rsold[rsodepth-1];
  521.                                     freeop(ap1);
  522.                                     ap3 = temp_data();
  523.                                     gen_code(op_lea,4,ap3,ap1);
  524.                                     ap3->mode = am_indisp;
  525.                                     ap3->offset = makenode(en_icon,0,0);
  526.                                     if (t <rsdepth-1 && ap3->preg + 8 == regstack[t+1])
  527.                                         t+=2;
  528.                                     if (t <rsdepth && ap3->preg + 8 == regstack[t])
  529.                                         t+=1;
  530.                                     ap1 = ap3;
  531.                                 }
  532.                         
  533.                         }
  534.                         release();
  535.                         break;
  536.                 }
  537.                 switch (node->v.p[1]->nodetype) {
  538.                     case en_icon:
  539.                         ap2 = gen_expr(node->v.p[1],F_IMMED,4);
  540.                         break;
  541.                     case en_lsh:
  542.                         if ((scale = node->v.p[1]->v.p[1]->v.i) < 4 && scale) {
  543.                             ap2 = gen_expr(node->v.p[1]->v.p[0],F_IMMED | F_DREG,4);
  544.                             if (ap2->mode == am_immed) {
  545.                                 while (--scale)
  546.                                     ap2->offset->v.i <<=1;
  547.                             }
  548.                             else {
  549.                                 ap2->mode = am_indispscale;
  550.                                 ap2->sreg = ap2->preg;
  551.                                 ap2->preg = -1;
  552.                                 ap2->scale = scale;
  553.                                 ap2->offset = makenode(en_icon,0,0);
  554.                             }
  555.                             break;
  556.                         }
  557.                     default:
  558.                         node2.v.p[0] = node->v.p[1];
  559.                         node2.nodetype = node->nodetype;
  560.                         mark();
  561.                         ap2 = gen_deref(&node2,F_MEM | F_DREG,4);
  562.                         switch (ap1->mode) {
  563.                             default:
  564.                                 rsold[rsodepth-1] = rsdepth;
  565.                                 break;
  566.                             case am_indispscale:
  567.                                 if (ap1->sreg >=0 && ap1->preg >= 0) {
  568.                                     int t = rsold[rsodepth-1];
  569.                                     freeop(ap1);
  570.                                     ap3 = temp_data();
  571.                                     gen_code(op_lea,4,ap3,ap1);
  572.                                     ap3->mode = am_indisp;
  573.                                     ap3->offset = makenode(en_icon,0,0);
  574.                                     if (t <rsdepth-1 && ap3->preg + 8 == regstack[t+1])
  575.                                         t+=2;
  576.                                     if (t <rsdepth && ap3->preg + 8 == regstack[t])
  577.                                         t+=1;
  578.                                     ap1 = ap3;
  579.                                 }
  580.                         
  581.                         }
  582.                         release();
  583.                         break;
  584.                 }
  585.                 switch(ap1->mode) {
  586.                     case am_dreg:
  587.                         switch (ap2->mode) {
  588.                             case am_dreg:
  589.                                 ap1->sreg = ap2->preg;
  590.                                 ap1->scale = 0;
  591.                                 ap1->mode = am_indispscale;
  592.                                 ap1->offset = makenode(en_icon,(char *)0,0);
  593.                                 return ap1;
  594.                             case am_immed:
  595.                             case am_direct:
  596.                                 ap2->preg = ap1->preg;
  597.                                 ap2->mode = am_indisp;
  598.                                 return ap2;    
  599.                             case am_indisp:
  600.                                 ap2->sreg = ap2->preg;
  601.                                 ap2->preg = ap1->preg;
  602.                                 ap2->mode = am_indispscale;
  603.                                 ap2->offset = ap1->offset;
  604.                                 ap2->scale = 0;
  605.                                 return ap2;
  606.                             case am_indispscale:
  607.                                 if (ap2->preg == -1) {
  608.                                     ap2->preg = ap1->preg;
  609.                                     return ap2;
  610.                                 }
  611.                                 freeop(ap2);
  612.                                 ap = temp_data();
  613.                                 gen_code(op_lea,4,ap,ap2);
  614.                                 ap->sreg = ap1->preg;
  615.                                 ap->mode = am_indispscale;
  616.                                 ap->scale = 0;
  617.                                 ap->offset = makenode(en_icon,0,0);
  618.                                 return ap;
  619.                         }
  620.                         break;
  621.                     case am_direct:
  622.                     case am_immed:
  623.                         switch (ap2->mode) {
  624.                             case am_dreg:
  625.                                 ap2->mode = am_indisp;
  626.                                 ap2->offset = ap1->offset;
  627.                                 return ap2;
  628.                             case am_immed:
  629.                             case am_direct:
  630.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  631.                                     ap1->offset->v.i += ap2->offset->v.i;
  632.                                 else
  633.                                     ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  634.                               ap1->mode = am_direct;
  635.                                 return ap1;
  636.                             case am_indisp:
  637.                             case am_indispscale:
  638.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  639.                                     ap2->offset->v.i += ap1->offset->v.i;
  640.                                 else
  641.                                     ap2->offset = makenode(en_add,ap1->offset,ap2->offset);
  642.                                 return ap2;
  643.                         }
  644.                         break;
  645.                     case am_indisp:
  646.                         switch (ap2->mode) {
  647.                             case am_dreg:
  648.                                 ap1->mode = am_indispscale;
  649.                                 ap1->sreg = ap2->preg;
  650.                                 ap1->scale = 0;
  651.                                 return ap1;
  652.                             case am_immed:
  653.                             case am_direct:
  654.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  655.                                     ap1->offset->v.i += ap2->offset->v.i;
  656.                                 else
  657.                                     ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  658.                                 return ap1;    
  659.                             case am_indisp:
  660.                                 ap1->mode = am_indispscale;
  661.                                 ap1->sreg = ap2->preg;
  662.                                 ap1->scale = 0;
  663.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  664.                                     ap1->offset->v.i += ap2->offset->v.i;
  665.                                 else
  666.                                     ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  667.                                 return ap1;
  668.                             case am_indispscale:
  669.                                 if (ap2->preg == -1) {
  670.                                     ap2->preg = ap1->preg;
  671.                                     if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  672.                                         ap2->offset->v.i += ap1->offset->v.i;
  673.                                     else
  674.                                         ap2->offset = makenode(en_add,ap1->offset,ap2->offset);
  675.                                     return ap2;
  676.                                 }
  677.                                 freeop(ap2);
  678.                                 ap = temp_data();
  679.                                 gen_code(op_lea,4,ap,ap2);
  680.                                 ap1->sreg = ap->preg;
  681.                                 ap1->scale = 0;
  682.                                 ap1->mode = am_indispscale;
  683.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  684.                                     ap1->offset->v.i += ap2->offset->v.i;
  685.                                 else
  686.                                     ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  687.                                 return ap1;
  688.                         }
  689.                         break;
  690.                     case am_indispscale:
  691.                         switch (ap2->mode) {
  692.                             case am_dreg:
  693.                                 if (ap1->preg == -1) {
  694.                                     ap1->preg = ap2->preg;
  695.                                     return ap1;
  696.                                 }
  697.                                 freeop(ap1);
  698.                                 ap = temp_data();
  699.                                 gen_code(op_lea,4,ap,ap1);
  700.                                 ap->sreg = ap2->preg;
  701.                                 ap->scale = 0;
  702.                                 ap->offset = ap1->offset;
  703.                                 return ap;
  704.                             case am_immed:
  705.                             case am_direct:
  706.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  707.                                     ap1->offset->v.i += ap2->offset->v.i;
  708.                                 else
  709.                                     ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  710.                                 return ap1;
  711.                             case am_indisp:
  712.                                 if (ap1->preg == -1) {
  713.                                     ap1->preg = ap2->preg;
  714.                                     if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  715.                                         ap1->offset->v.i += ap2->offset->v.i;
  716.                                     else
  717.                                         ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  718.                                     return ap1;
  719.                                 }
  720.                                 freeop(ap1);
  721.                                 ap = temp_data();
  722.                                 gen_code(op_lea,4,ap,ap1);
  723.                                 ap->sreg = ap2->preg;
  724.                                 ap->scale = 0;
  725.                                 ap->mode = am_indispscale;
  726.                                 if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  727.                                     ap->offset->v.i = ap2->offset->v.i +ap1->offset->v.i;
  728.                                 else
  729.                                     ap->offset = makenode(en_add,ap1->offset,ap2->offset);
  730.                                 return ap;
  731.                             case am_indispscale:
  732.                                 if (ap1->preg == -1 && ap2->preg == -1) {
  733.                                     if (ap1->scale == 0) {
  734.                                         ap2->preg = ap1->sreg;
  735.                                         if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  736.                                             ap2->offset->v.i += ap1->offset->v.i;
  737.                                         else
  738.                                             ap2->offset = makenode(en_add,ap1->offset,ap2->offset);
  739.                                         return ap2;
  740.                                     } else if (ap2->scale == 0) {
  741.                                         ap1->preg = ap2->sreg;
  742.                                         if (ap1->offset->nodetype == en_icon && ap2->offset->nodetype == en_icon)
  743.                                             ap1->offset->v.i += ap2->offset->v.i;
  744.                                         else
  745.                                             ap1->offset = makenode(en_add,ap1->offset,ap2->offset);
  746.                                         return ap1;
  747.                                     }
  748.                                 }
  749.                                 if (ap1->preg == -1) {
  750.                                     freeop(ap2);
  751.                                     ap = temp_data();
  752.                                     gen_code(op_lea,4,ap,ap2);
  753.                                     ap1->preg = ap->preg;
  754.                                     return ap1;
  755.                                 }
  756.                                 else if (ap2->preg == -1) {
  757.                                     freeop(ap1);
  758.                                     ap = temp_data();
  759.                                     gen_code(op_lea,4,ap,ap1);
  760.                                     ap2->preg = ap->preg;
  761.                                     return ap2;
  762.                                 }
  763.                                 freeop(ap1);
  764.                                 ap = temp_data();
  765.                                 gen_code(op_lea,4,ap,ap1);
  766.                                 freeop(ap2);
  767.                                 ap1 = temp_data();
  768.                                 gen_code(op_lea,4,ap1,ap2);
  769.                                 ap->mode = am_indispscale;
  770.                                 ap->sreg = ap1->preg;
  771.                                 ap->scale = 0;
  772.                                 ap->offset = makenode(en_icon,0,0);
  773.                                 return ap;
  774.                         }
  775.                         break;           
  776.                 }
  777.                 DIAG("invalid index conversion");
  778. }
  779.  
  780. AMODE    *gen_deref(ENODE *node, int flags,int size)
  781. /*
  782.  *      return the addressing mode of a dereferenced node.
  783.  */
  784. {       AMODE    *ap1;
  785.         int             ssize,psize;
  786.                 psize = size;
  787.                 if (psize < 0)
  788.                     psize = - psize;
  789.         switch( node->nodetype )        /* get load size */
  790.                 {
  791.                 case en_ub_ref:
  792.                         ssize = 1;
  793.                         break;
  794.                 case en_b_ref:
  795.                         ssize = -1;
  796.                         break;
  797.                 case en_uw_ref:
  798.                         ssize = 2;
  799.                         break;
  800.                 case en_w_ref:
  801.                         ssize = -2;
  802.                         break;
  803.                 case en_l_ref:
  804.                                                 ssize = -4;
  805.                                                 break;
  806.                                 case en_ul_ref:
  807.                         ssize = 4;
  808.                         break;
  809.                                 case en_floatref:
  810.                                                 ssize = 6;
  811.                                                 break;
  812.                                 case en_doubleref:
  813.                                                 ssize = 8;
  814.                                                 break;
  815.                                 case en_longdoubleref:
  816.                                                 ssize = 10;
  817.                                                 break;
  818.                                 default:
  819.                                                 ssize = 4;
  820.                 }
  821.         if( node->v.p[0]->nodetype == en_add )
  822.                 {
  823.                 ap1 = gen_index(node->v.p[0]);
  824.                 do_extend(ap1,ssize,psize,flags);
  825.                 make_legal(ap1,flags,psize);
  826.                 return ap1;
  827.                 }
  828.         else if( node->v.p[0]->nodetype == en_autocon  || node->v.p[0]->nodetype == en_autoreg)
  829.                 {
  830.                 ap1 = xalloc(sizeof(AMODE));
  831.                 ap1->mode = am_indisp;
  832.                                 ap1->preg = ESP;
  833.                                 if (prm_linkreg) {
  834.                           ap1->preg = EBP;
  835.                           ap1->offset = makenode(en_icon,(char *)((SYM *)node->v.p[0]->v.p[0])->value.i,0);
  836.                                 }
  837.                                 else if (((SYM *)node->v.p[0]->v.p[0])->funcparm)
  838.                     ap1->offset = makenode(en_icon,(char *)(((SYM *)node->v.p[0]->v.p[0])->value.i+framedepth+stackdepth),0);
  839.                 else
  840.                                     ap1->offset = makenode(en_icon,(char *)(((SYM *)node->v.p[0]->v.p[0])->value.i+stackdepth+lc_maxauto),0);
  841.                 do_extend(ap1,ssize,size,flags);
  842.                 make_legal(ap1,flags,psize);
  843.                 return ap1;
  844.                 }
  845.         else if( node->v.p[0]->nodetype == en_nacon || node->v.p[0]->nodetype == en_napccon)
  846.                 {
  847.                 ap1 = xalloc(sizeof(AMODE));
  848.                 ap1->offset = makenode(node->v.p[0]->nodetype,(char *)((SYM *)node->v.p[0]->v.p[0])->name,0);
  849.                 ap1->mode = am_direct;
  850.                 do_extend(ap1,ssize,size,flags);
  851.                 make_legal(ap1,flags,psize);
  852.                 return ap1;
  853.                 }
  854.         else if( node->v.p[0]->nodetype == en_nalabcon)
  855.                 {
  856.                 ap1 = xalloc(sizeof(AMODE));
  857.                 ap1->offset = makenode(node->v.p[0]->nodetype,(char *)node->v.p[0]->v.i,0);
  858.                 ap1->mode = am_direct;
  859.                 do_extend(ap1,ssize,size,flags);
  860.                 make_legal(ap1,flags,psize);
  861.                 return ap1;
  862.                 }
  863.         else if( node->v.p[0]->nodetype == en_labcon)
  864.                 {
  865.                 ap1 = xalloc(sizeof(AMODE));
  866.                 ap1->mode = am_direct;
  867.                 ap1->offset = makenode(node->v.p[0]->nodetype,(char *)node->v.p[0]->v.i,0);
  868.                 do_extend(ap1,ssize,size,flags);
  869.                 make_legal(ap1,flags,psize);
  870.                 return ap1;
  871.                 }
  872.                 else if (node->v.p[0]->nodetype == en_absacon) {
  873.                                 ap1 = xalloc(sizeof(AMODE));
  874.                                 ap1->mode = am_direct;
  875.                                 ap1->offset = makenode(en_absacon,(char *)((SYM *)node->v.p[0]->v.p[0])->value.i,0);
  876.                 do_extend(ap1,ssize,size,flags);
  877.                 make_legal(ap1,flags,psize);
  878.                 return ap1;
  879.  
  880.                 }
  881.                 else if (node->v.p[0]->nodetype == en_regref) {
  882.             ap1 = gen_expr(node->v.p[0],F_ALL,4);
  883.           do_extend(ap1,ssize,size,flags);
  884.           make_legal(ap1,flags,psize);
  885.                     return ap1;
  886.                 }
  887.         ap1 = gen_expr(node->v.p[0],F_DREG | F_IMMED,4); /* generate address */
  888.         if( ap1->mode == am_dreg )
  889.                 {
  890.                 ap1->mode = am_indisp;
  891.                                 ap1->offset = makenode(en_icon,0,0);
  892.                       do_extend(ap1,ssize,size,flags);
  893.                         make_legal(ap1,flags,psize);
  894.                 return ap1;
  895.                 }
  896.         ap1->mode = am_direct;
  897.         do_extend(ap1,ssize,size,flags);
  898.         make_legal(ap1,flags,psize);
  899.         return ap1;
  900. }
  901.  
  902. AMODE    *gen_unary(ENODE *node,int flags,int size,int op, int fop)
  903. /*
  904.  *      generate code to evaluate a unary minus or complement.
  905.  */
  906. {       AMODE    *ap;
  907.         ap = gen_expr(node->v.p[0],F_FREG | F_DREG | F_VOL,size);
  908.                 if (ap->mode == am_freg) {
  909.                     gen_code(fop,0,0,0);
  910.                     ap = fstack();
  911.                 }
  912.                 else {
  913.             gen_code(op,size,ap,0);
  914.                 }
  915.         make_legal(ap,flags,size);
  916.         return ap;
  917. }
  918.  
  919. AMODE    *gen_binary(ENODE *node,int flags,int size,int op, int fop)
  920. /*
  921.  *      generate code to evaluate a binary node and return 
  922.  *      the addressing mode of the result.
  923.  */
  924. {       AMODE    *ap1, *ap2;
  925.                 if (size > 4) {
  926.             ap1 = gen_expr(node->v.p[0],F_VOL | F_FREG,size);
  927.                     mark();
  928.             ap2 = gen_expr(node->v.p[1],F_MEM | F_FREG,size);
  929.                     if (ap2->mode == am_freg)
  930.                         gen_code(fop,0,0,0);
  931.                     else {
  932.                         int t;
  933.                         t = natural_size(node->v.p[1]);
  934.                         if (t== 0) t = size;
  935.                         if (t <=4)
  936.                             if (fop == op_fadd)
  937.                                 fop = op_fiadd;
  938.                             else
  939.                                 fop = op_fisub;
  940.                         gen_f10code(fop,t,ap2,0);
  941.                     }
  942.                     ap1 = fstack();
  943.                 }
  944.                 else {
  945.             ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG,size);
  946.                     mark();
  947.             ap2 = gen_expr(node->v.p[1],F_ALL,size);
  948.             gen_code(op,size,ap1,ap2);
  949.                 }
  950.         freeop(ap2);
  951.                 release();
  952.         make_legal(ap1,flags,size);
  953.         return ap1;
  954. }
  955.  
  956. AMODE    *gen_xbin(ENODE *node,int flags,int size,int op, int fop)
  957. /*
  958.  *      generate code to evaluate a restricted binary node and return 
  959.  *      the addressing mode of the result.
  960.  */
  961. {       AMODE    *ap1, *ap2;
  962.                 if (size > 4) {
  963.             ap1 = gen_expr(node->v.p[0],F_VOL | F_FREG,size);
  964.                     mark();
  965.             ap2 = gen_expr(node->v.p[1],F_MEM | F_FREG,size);
  966.                     if (ap2->mode == am_freg)
  967.                         gen_code(fop,0,0,0);
  968.                     else
  969.                         gen_code(fop,size,ap2,0);
  970.                     ap1 = fstack();
  971.                 }
  972.                 else {
  973.             ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG,size);
  974.                     mark();
  975.             ap2 = gen_expr(node->v.p[1],F_ALL,size);
  976.             gen_code(op,size,ap2,ap1);
  977.                 }
  978.                 release();
  979.         freeop(ap2);
  980.         make_legal(ap1,flags,size);
  981.         return ap1;
  982. }
  983. void doshift(AMODE *ap1, AMODE *ap2, int size, int op)
  984. {       AMODE   *ecx = makedreg(ECX), *eax = makedreg(EAX);
  985.                 if (ap2->mode == am_immed) {
  986.                     gen_code2(op,size,1,ap1,ap2);
  987.                 }
  988.                 else
  989.                     if (ap1->mode == am_dreg && ap1->preg == ECX) {
  990.                             if (ap2->mode == am_dreg) {
  991.                                 gen_code(op_xchg,4,ap2,ap1);
  992.                                 gen_code2(op,size,1,ap2,ecx);
  993.                                 gen_code(op_xchg,4,ap2,ap1);
  994.                             }
  995.                             else {
  996.                                 if (regs[0])
  997.                                     gen_push(EAX,am_dreg,0);
  998.                                 gen_code(op_xchg,4,eax,ecx);
  999.                                 gen_code(op_mov,1,ap2,ecx);
  1000.                                 gen_code2(op,size,1,eax,ecx);
  1001.                                 gen_code(op_xchg,4,eax,ecx);
  1002.                                 if (regs[0])
  1003.                                     gen_pop(EAX,am_dreg,0);
  1004.                             }
  1005.                     }
  1006.                     else
  1007.                         if (ap2->mode == am_dreg) {
  1008.                             if (ap2->preg != ECX)
  1009.                                 gen_code(op_xchg,4,ap2,ecx);
  1010.                             gen_code2(op,size,1,ap1,ecx);
  1011.                             if (ap2->preg != ECX)
  1012.                                 gen_code(op_xchg,4,ap2,ecx);
  1013.                         }
  1014.                         else {
  1015.                             if (regs[1])
  1016.                                 gen_push(ECX,am_dreg,0);
  1017.                             gen_code(op_mov,4,ap2,ecx);
  1018.                             gen_code2(op,size,1,ap1,ecx);
  1019.                             if (regs[1])
  1020.                                 gen_pop(ECX,am_dreg,0);
  1021.                         }
  1022. }
  1023. AMODE    *gen_shift(ENODE *node, int flags, int size, int op)
  1024. /*
  1025.  *      generate code to evaluate a shift node and return the
  1026.  *      address mode of the result.
  1027.  */
  1028. {       AMODE    *ap1, *ap2;
  1029.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  1030.                 mark();
  1031.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,natural_size(node->v.p[1]));
  1032.                 doshift(ap1,ap2,size,op);
  1033.         freeop(ap2);
  1034.                 release();
  1035.         make_legal(ap1,flags,size);
  1036.         return ap1;
  1037. }
  1038. void dodiv(AMODE *ap1, AMODE *ap2, int size, int op,int modflag)
  1039. {
  1040.     AMODE *eax = makedreg(EAX), *edx = makedreg(EDX), *ecx = makedreg(ECX);
  1041.     if (ap2->mode == am_immed) {
  1042.         ap2 = make_muldivval(ap2);
  1043.     }
  1044.     if (ap1->preg != EAX) {
  1045.         int temp;
  1046.         gen_code(op_xchg,4,eax,ap1);
  1047.         if (ap1->mode == am_dreg && ap2->mode == am_dreg && ap1->preg == ap2->preg) {
  1048.             gen_code(op,4,eax,0);
  1049.             gen_code(op_xchg,4,eax,ap1);
  1050.             return;
  1051.         }
  1052.         temp = regs[0];
  1053.         regs[0] = regs[ap1->preg];
  1054.         regs[ap1->preg] = temp;
  1055.     }
  1056.     if (ap2->preg == EDX) {
  1057.         if (regs[1])
  1058.             gen_push(ECX,am_dreg,0);
  1059.         if (regs[2])
  1060.             gen_push(EDX,am_dreg,0);
  1061.         gen_code(op_mov,4,ecx,edx);
  1062.         gen_code(op_sub,4,edx,edx);
  1063.         gen_code(op,4,ecx,0);
  1064.         if (modflag)
  1065.             gen_code(op_xchg,4,eax,edx);
  1066.         if (regs[2])
  1067.             gen_pop(EDX,am_dreg,0);
  1068.         if (regs[1])
  1069.             gen_pop(ECX,am_dreg,0);
  1070.     }
  1071.     else {
  1072.         if (regs[2])
  1073.             gen_push(EDX,am_dreg,0);
  1074.         gen_code(op_sub,4,edx,edx);
  1075.         gen_code(op,4,ap2,0);
  1076.         if (modflag)
  1077.             gen_code(op_xchg,4,eax,edx);
  1078.         if (regs[2])
  1079.             gen_pop(EDX,am_dreg,0);
  1080.     }
  1081.     if (ap1->preg != EAX) {
  1082.         int temp;
  1083.         gen_code(op_xchg,4,eax,ap1);
  1084.         temp = regs[0];
  1085.         regs[0] = regs[ap1->preg];
  1086.         regs[ap1->preg] = temp;
  1087.     }
  1088. }
  1089. void domul(AMODE *ap1, AMODE *ap2, int size, int op)
  1090. {
  1091.     AMODE *eax = makedreg(EAX), *edx = makedreg(EDX), *ecx = makedreg(ECX);
  1092.     if (ap2->mode == am_immed) {
  1093.         ap2 = make_muldivval(ap2);
  1094.     }
  1095.     if (ap1->preg != EAX) {
  1096.         int temp;
  1097.         gen_code(op_xchg,4,eax,ap1);
  1098.         if (ap1->mode == am_dreg && ap2->mode == am_dreg && ap1->preg == ap2->preg && ap1->preg != EDX) {
  1099.             gen_code(op,4,eax,0);
  1100.             gen_code(op_xchg,4,eax,ap1);
  1101.             return;
  1102.         }
  1103.         temp = regs[0];
  1104.         regs[0] = regs[ap1->preg];
  1105.         regs[ap1->preg] = temp;
  1106.     }
  1107.     if (ap2->preg == EDX) {
  1108.         if (regs[1])
  1109.             gen_push(ECX,am_dreg,0);
  1110.         if (regs[2])
  1111.             gen_push(EDX,am_dreg,0);
  1112.         gen_code(op_mov,4,ecx,edx);
  1113.         gen_code(op_sub,4,edx,edx);
  1114.         gen_code(op,4,ecx,0);
  1115.         if (regs[2])
  1116.             gen_pop(EDX,am_dreg,0);
  1117.         if (regs[1])
  1118.             gen_pop(ECX,am_dreg,0);
  1119.     }
  1120.     else {
  1121.         if (regs[2])
  1122.             gen_push(EDX,am_dreg,0);
  1123.         gen_code(op,4,ap2,0);
  1124.         if (regs[2])
  1125.             gen_pop(EDX,am_dreg,0);
  1126.     }
  1127.     if (ap1->preg != EAX) {
  1128.         int temp;
  1129.         gen_code(op_xchg,4,eax,ap1);
  1130.         temp = regs[0];
  1131.         regs[0] = regs[ap1->preg];
  1132.         regs[ap1->preg] = temp;
  1133.     }
  1134. }
  1135. AMODE    *gen_modiv(ENODE *node, int flags, int size, int op, int modflag)
  1136. /*
  1137.  *      generate code to evaluate a mod operator or a divide
  1138.  *      operator. these operations are done on only long
  1139.  *      divisors and word dividends so that the 68000 div
  1140.  *      instruction can be used.
  1141.  */
  1142. {       AMODE    *ap1, *ap2;
  1143.                 
  1144.                 if (size > 4) {
  1145.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL,size);
  1146.                     ap2 = gen_expr(node->v.p[1],F_ALL,size);
  1147.                     op = op_fdiv;
  1148.                     if (ap2->mode == am_freg)
  1149.                         gen_code(op,0,0,0);
  1150.                     else {
  1151.                         int t;
  1152.                         t = natural_size(node->v.p[1]);
  1153.                         if (t== 0) t = size;
  1154.                         if (t <=4)
  1155.                             op = op_fidiv;
  1156.                         gen_f10code(op,t,ap2,0);
  1157.                     }
  1158.                     ap1 = fstack();
  1159.                     do_extend(ap1,10,size,flags);
  1160.                     make_legal(ap1,flags,size);
  1161.                     return ap1;
  1162.                 }
  1163.                     if (op == op_idiv) {
  1164.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,-4);
  1165.                     }
  1166.                     else {
  1167.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  1168.                     }
  1169.                     mark();
  1170.                     if (op == op_idiv) {
  1171.                 ap2 = gen_expr(node->v.p[1],F_ALL,-4);
  1172.                     }
  1173.                     else {
  1174.                 ap2 = gen_expr(node->v.p[1],F_ALL,4);
  1175.                     }
  1176.                     dodiv(ap1,ap2,size,op,modflag);
  1177.                     freeop(ap2);
  1178.                     release();
  1179.             make_legal(ap1,flags,size);
  1180.             return ap1;
  1181.                     
  1182. }
  1183.  
  1184.  
  1185. void swap_nodes(ENODE *node)
  1186. /*
  1187.  *      exchange the two operands in a node.
  1188.  */
  1189. {       ENODE    *temp;
  1190.         temp = node->v.p[0];
  1191.         node->v.p[0] = node->v.p[1];
  1192.         node->v.p[1] = temp;
  1193. }
  1194.  
  1195. AMODE * gen_pdiv(ENODE *node, int flags, int size)
  1196. {
  1197.                 return gen_modiv(node,flags,size,op_div,FALSE);
  1198. }            
  1199. AMODE * gen_pmul(ENODE *node, int flags, int size)
  1200. {
  1201.                 return gen_mul(node,flags,size,op_mul);
  1202. }            
  1203. AMODE    *gen_mul(ENODE *node, int flags, int size, int op)
  1204. /*
  1205.  *      generate code to evaluate a multiply node. both operands
  1206.  *      are treated as words and the result is long and is always
  1207.  *      in a register so that the 68000 mul instruction can be used.
  1208.  */
  1209. {       AMODE    *ap1, *ap2;
  1210.  
  1211.                 if (isintconst(node->v.p[0]->nodetype))
  1212.                     swap_nodes(node);                
  1213.                 if (size > 4) {
  1214.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL,size);
  1215.                     ap2 = gen_expr(node->v.p[1],F_ALL,size);
  1216.                     op = op_fmul;
  1217.                     if (ap2->mode == am_freg)
  1218.                         gen_code(op,0,0,0);
  1219.                     else {
  1220.                         int t;
  1221.                         t = natural_size(node->v.p[1]);
  1222.                         if (t== 0) t = size;
  1223.                         if (t <=4)
  1224.                             op = op_fimul;
  1225.                         gen_f10code(op,t,ap2,0);
  1226.                     }
  1227.                     ap1 = fstack();
  1228.                     do_extend(ap1,10,size,flags);
  1229.                     make_legal(ap1,flags,size);
  1230.                     return ap1;
  1231.                 }
  1232.                     if (op == op_imul) {
  1233.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,-4);
  1234.                     }
  1235.                     else {
  1236.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  1237.                     }
  1238.                     mark();
  1239.                     if (op == op_imul) {
  1240.                 ap2 = gen_expr(node->v.p[1],F_ALL,-4);
  1241.                     }
  1242.                     else {
  1243.                 ap2 = gen_expr(node->v.p[1],F_ALL,4);
  1244.                     }
  1245.                     domul(ap1,ap2,size,op);
  1246.                     freeop(ap2);
  1247.                     release();
  1248.                     do_extend(ap1,4,size,flags);
  1249.             make_legal(ap1,flags,size);
  1250.             return ap1;
  1251. }
  1252. AMODE    *gen_hook(ENODE *node, int flags, int size)
  1253. /*
  1254.  *      generate code to evaluate a condition operator node (?:)
  1255.  */
  1256. {       AMODE    *ap1, *ap2;
  1257.         int             false_label, end_label;
  1258.         false_label = nextlabel++;
  1259.         end_label = nextlabel++;
  1260.         flags = (flags & (F_AREG | F_DREG)) | F_VOL;
  1261.         falsejp(node->v.p[0],false_label);
  1262.         node = node->v.p[1];
  1263.         ap1 = gen_expr(node->v.p[0],flags,size);
  1264.         freeop(ap1);
  1265.         gen_code(op_jmp,0,make_label(end_label),0);
  1266.         gen_label(false_label);
  1267.         ap2 = gen_expr(node->v.p[1],flags,size);
  1268.         if( !equal_address(ap1,ap2) )
  1269.                 {
  1270.                 freeop(ap2);
  1271.                 temp_data();
  1272.                 gen_code(op_mov,size,ap2,ap1);
  1273.                 }
  1274.         gen_label(end_label);
  1275.         return ap1;
  1276. }
  1277.  
  1278. void floatstore(AMODE *ap, int size, int flags)
  1279. {
  1280.     if (size <= 4)
  1281.                         if (flags & F_NOVALUE)
  1282.                           gen_codef(op_fistp,size,ap,0);
  1283.                         else
  1284.                           gen_codef(op_fist,size,ap,0);
  1285.     else
  1286.                         if (flags & F_NOVALUE)
  1287.                           gen_codef(op_fstp,size,ap,0);
  1288.                         else
  1289.                           gen_codef(op_fst,size,ap,0);
  1290. }
  1291. AMODE    *gen_asadd(ENODE *node, int flags, int size, int op, int fop)
  1292. /*
  1293.  *      generate a plus equal or a minus equal node.
  1294.  */
  1295. {       AMODE    *ap1, *ap2, *ap3;
  1296.         int             ssize,rsize;
  1297.         ssize = natural_size(node->v.p[0]);
  1298.         rsize = natural_size(node->v.p[1]);
  1299.                 if (rsize == 0)
  1300.                     rsize = ssize;
  1301.                 if (rsize > 4) {
  1302.                     ap2 = gen_expr(node->v.p[0],F_FREG,rsize);
  1303.                     ap3 = gen_expr(node->v.p[0],F_MEM,ssize);
  1304.                     ap1 = gen_expr(node->v.p[1],F_FREG | F_MEM,rsize);
  1305.                     if (ap1->mode == am_freg)
  1306.                         gen_code(fop,0,0,0);
  1307.                     else {
  1308.                         if (rsize <= 4)
  1309.                             if (fop == op_fadd)
  1310.                                 fop = op_fiadd;
  1311.                             else
  1312.                                 fop = op_fisub;
  1313.                         gen_f10code(fop,rsize,ap1,0);
  1314.                     }
  1315.                     floatstore(ap3,ssize,flags);
  1316.                     gen_codef(op_fwait,0,0,0);
  1317.                     if (!(flags & F_NOVALUE)) {
  1318.                         ap2 = fstack();
  1319.                         do_extend(ap2,ssize,size,flags);
  1320.                         make_legal(ap2,flags,size);
  1321.                     }
  1322.                     return ap2;
  1323.                 }
  1324.         if (chksize( ssize ,rsize ))
  1325.                 rsize = ssize;
  1326.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1327.                 mark();
  1328.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,rsize);
  1329.                 if (node->v.p[0]->nodetype == en_bits)
  1330.                     ap3= get_bitval(ap2,node->v.p[0],ssize);
  1331.                 if (node->v.p[0]->nodetype == en_bits) {
  1332.                     gen_code(op,ssize,ap3,ap1);
  1333.                     bit_move(ap2,ap3,node->v.p[0],flags, ssize,rsize);
  1334.                     freeop(ap3);
  1335.                 }
  1336.                 else
  1337.                gen_code(op,ssize,ap2,ap1);
  1338.                 freeop(ap1);
  1339.                 release();
  1340.                 if (flags & F_NOVALUE)
  1341.                     freeop(ap2);
  1342.                 else {
  1343.                     do_extend(ap2,ssize,size,flags);
  1344.                make_legal(ap2,flags,4);
  1345.                 }
  1346.         return ap2;
  1347. }
  1348.  
  1349. AMODE    *gen_aslogic(ENODE *node, int flags, int size, int op)
  1350. /*
  1351.  *      generate a and equal or a or equal node.
  1352.  */
  1353. {       AMODE    *ap1, *ap2;
  1354.         int             ssize,rsize;
  1355.         ssize = natural_size(node->v.p[0]);
  1356.         rsize = natural_size(node->v.p[1]);
  1357.         if (chksize( ssize , rsize ))
  1358.                 rsize = ssize;
  1359.             
  1360.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1361.                 mark();
  1362.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,rsize);
  1363.                 if (node->v.p[0]->nodetype == en_bits) {
  1364.                     if (ap1->mode == am_immed) {
  1365.                         ap1->offset->v.i &= bittab[node->v.p[0]->bits-1];
  1366.                         ap1->offset->v.i <<= node->v.p[0]->startbit;
  1367.                         gen_code(op,ssize,ap2,ap1);
  1368.                     }
  1369.                     else {
  1370.                       gen_code(op_and,ssize,ap1,make_immed(bittab[node->v.p[0]->bits-1]));
  1371.                         if (node->v.p[0]->startbit)
  1372.                           gen_code(op_shl,ssize,ap1,make_immed(node->v.p[0]->startbit));
  1373.                         gen_code(op,ssize,ap2,ap1);
  1374.                         if (!(flags & F_NOVALUE)) {
  1375.                             freeop(ap1);
  1376.                             release();
  1377.                             if (node->v.p[0]->startbit)
  1378.                               gen_code(op_shr,ssize,ap2,make_immed(node->v.p[0]->startbit));
  1379.                     do_extend(ap2,ssize,size,0);
  1380.                             make_legal(ap2,F_DREG,size);
  1381.                             return(ap2);
  1382.                         }
  1383.                     }
  1384.                 }
  1385.                 else
  1386.             gen_code(op,ssize,ap2,ap1);
  1387.                 freeop(ap1);
  1388.                 release();
  1389.                 if (flags & F_NOVALUE)
  1390.                     freeop(ap2);
  1391.                 else {
  1392.                     do_extend(ap2,ssize,size,flags);
  1393.             make_legal(ap2,flags,4);
  1394.                 }
  1395.         return ap2;
  1396. }
  1397.  
  1398. AMODE *gen_asshift(ENODE *node, int flags, int size, int op)
  1399. /*
  1400.  *      generate shift equals operators.
  1401.  */
  1402. {       
  1403.         AMODE    *ap1, *ap2, *ap3;
  1404.         int ssize = natural_size(node->v.p[0]);
  1405.         int rsize = natural_size(node->v.p[1]);
  1406.         if (chksize( ssize , rsize ))
  1407.                 rsize = rsize;
  1408.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1409.                 mark();
  1410.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,rsize);
  1411.                 if (node->v.p[0]->nodetype == en_bits)
  1412.                     ap3 = get_bitval(ap2,node->v.p[0],ssize);
  1413.                 else
  1414.                     ap3 = ap2;
  1415.  
  1416.                 doshift(ap3,ap1,ssize,op);
  1417.                 if (node->v.p[0]->nodetype == en_bits)
  1418.                     bit_move(ap2,ap3,node->v.p[0],flags,ssize,rsize);
  1419.                 freeop(ap1);
  1420.                 release();
  1421.                 if (ap3 != ap1)
  1422.                     freeop(ap3);
  1423.                 if (flags & F_NOVALUE)
  1424.                     freeop(ap2);
  1425.                 else {
  1426.                     do_extend(ap2,ssize,size,flags);
  1427.                make_legal(ap2,flags,4);
  1428.                 }
  1429.             return ap2;
  1430. }
  1431.  
  1432. AMODE    *gen_asmul(ENODE *node, int flags, int size,int op)
  1433. /*
  1434.  *      generate a *= node.
  1435.  */
  1436. {       AMODE    *ap1, *ap2,*ap3;
  1437.         int             ssize, lsize,rsize;
  1438.         ssize = natural_size(node->v.p[0]);
  1439.         rsize = natural_size(node->v.p[1]);
  1440.                 if (rsize == 0)
  1441.                     rsize = ssize;
  1442.                 if (rsize > 4) {
  1443.                     int fop = op_fmul;
  1444.                     ap2 = gen_expr(node->v.p[0],F_FREG,rsize);
  1445.                     ap3 = gen_expr(node->v.p[0],F_MEM,ssize);
  1446.                     ap1 = gen_expr(node->v.p[1],F_FREG | F_MEM,rsize);
  1447.                     if (ap1->mode == am_freg)
  1448.                         gen_code(fop,0,0,0);
  1449.                     else {
  1450.                         if (rsize <= 4)
  1451.                             fop = op_fimul;
  1452.                         gen_f10code(fop,ssize,ap1,0);
  1453.                     }
  1454.                     floatstore(ap3,ssize,flags);
  1455.                     gen_codef(op_fwait,0,0,0);
  1456.                     if (!(flags & F_NOVALUE)) {
  1457.                         ap2 = fstack();
  1458.                         do_extend(ap2,ssize,size,flags);
  1459.                         make_legal(ap2,flags,size);
  1460.                     }
  1461.                     return ap2;
  1462.                 }
  1463.                 if (op == op_imul)
  1464.                     lsize= -4;
  1465.                 else
  1466.                     lsize = 4;
  1467.           ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1468.                 mark();
  1469.           ap1 = gen_expr(node->v.p[1],F_ALL,lsize);
  1470.                 ap3 = xalloc(sizeof(AMODE));
  1471.                 ap3->mode = ap2->mode;
  1472.                 ap3->preg = ap2->preg;
  1473.                 ap3->sreg = ap2->sreg;
  1474.                 ap3->scale = ap2->scale;
  1475.                 ap3->offset = ap2->offset;
  1476.                 if (node->v.p[0]->nodetype == en_bits)
  1477.                     ap2 = get_bitval(ap2,node->v.p[0],ssize);
  1478.                 else {
  1479.             make_legal(ap2,F_DREG | F_VOL,4);
  1480.                     do_extend(ap2,ssize,lsize,F_DREG);
  1481.                 }
  1482.                 domul(ap2,ap1,lsize,op);
  1483.                 freeop(ap1);
  1484.                 release();
  1485.                 if (!equal_address(ap2,ap3))
  1486.                     if (node->v.p[0]->nodetype == en_bits)
  1487.                         bit_move(ap3,ap2,node->v.p[0],flags,ssize,rsize);
  1488.                     else
  1489.                         gen_code(op_mov,ssize,ap3,ap2);
  1490.                 if (flags & F_NOVALUE)
  1491.                     freeop(ap2);
  1492.                 else {
  1493.                     do_extend(ap2,ssize,size,flags);
  1494.                make_legal(ap2,flags,4);
  1495.                 }
  1496.         return ap2;
  1497. }
  1498.  
  1499. AMODE    *gen_asmodiv(ENODE *node, int flags, int size, int op, int modflag)
  1500. /*
  1501.  *      generate /= and %= nodes.
  1502.  */
  1503. {       AMODE    *ap1, *ap2,*ap3;
  1504.         int             ssize,lsize,rsize;
  1505.         ssize = natural_size(node->v.p[0]);
  1506.         rsize = natural_size(node->v.p[1]);
  1507.                 if (rsize == 0)
  1508.                     rsize = ssize;
  1509.                 if (rsize > 4) {
  1510.                     int fop = op_fdiv;
  1511.                     ap2 = gen_expr(node->v.p[0],F_FREG,rsize);
  1512.                     ap3 = gen_expr(node->v.p[0],F_MEM,ssize);
  1513.                     ap1 = gen_expr(node->v.p[1],F_FREG | F_MEM,rsize);
  1514.                     if (ap1->mode == am_freg)
  1515.                         gen_code(fop,0,0,0);
  1516.                     else {
  1517.                         if (rsize <= 4)
  1518.                             fop = op_fidiv;
  1519.                         gen_f10code(fop,ssize,ap1,0);
  1520.                     }
  1521.                     floatstore(ap3,ssize,flags);
  1522.                     gen_codef(op_fwait,0,0,0);
  1523.                     if (!(flags & F_NOVALUE)) {
  1524.                         ap2 = fstack();
  1525.                         do_extend(ap2,ssize,size,flags);
  1526.                         make_legal(ap2,flags,size);
  1527.                     }
  1528.                     return ap2;
  1529.                 }                                                   
  1530.                 if (op == op_idiv)                                  
  1531.                     lsize= -4;                                        
  1532.                 else                                                
  1533.                     lsize = 4;                                        
  1534.                                                                   
  1535.            ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST, ssize);         
  1536.                 mark();
  1537.            ap1 = gen_expr(node->v.p[1],F_ALL,lsize);         
  1538.                 ap3 = xalloc(sizeof(AMODE));                      
  1539.                 ap3->mode = ap2->mode;                            
  1540.                 ap3->preg = ap2->preg;                            
  1541.                 ap3->sreg = ap2->sreg;                            
  1542.                 ap3->scale = ap2->scale;                          
  1543.                 ap3->offset = ap2->offset;
  1544.                 if (node->v.p[0]->nodetype == en_bits)
  1545.                     ap2 = get_bitval(ap2,node->v.p[0],ssize);
  1546.                 else {
  1547.             make_legal(ap2,F_DREG | F_VOL,4);
  1548.                     do_extend(ap2,ssize,lsize,F_DREG);
  1549.                 }
  1550.                 dodiv(ap2,ap1,ssize,op,modflag);                  
  1551.                 freeop(ap1);
  1552.                 release();
  1553.                 if (!equal_address(ap2,ap3))
  1554.                     if (node->v.p[0]->nodetype == en_bits)
  1555.                         bit_move(ap3,ap2,node->v.p[0],flags,ssize,rsize);
  1556.                     else
  1557.                         gen_code(op_mov,ssize,ap3,ap2);
  1558.                 if (flags & F_NOVALUE)                              
  1559.                     freeop(ap2);                                      
  1560.                 else {
  1561.                     do_extend(ap2,ssize,size,flags);
  1562.                make_legal(ap2,flags,4);
  1563.                 }
  1564.            return ap2;                                       
  1565. }
  1566. AMODE *gen_moveblock(ENODE *node, int flags, int size)      
  1567. {                                                           
  1568.     AMODE *ap1, *ap2;                                         
  1569.     if (!node->size)                                          
  1570.         return(0);
  1571.     ap2 = gen_expr(node->v.p[1],F_DREG | F_VOL,4);                     
  1572.     mark();
  1573.     ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);                     
  1574.     gen_push(ESI,am_dreg,0);                                  
  1575.     gen_push(EDI,am_dreg,0);                                  
  1576.     if (regs[1])                                              
  1577.         gen_push(ECX,am_dreg,0);                                
  1578.     gen_code(op_mov,4,makedreg(ESI),ap2);                          
  1579.     gen_code(op_mov,4,makedreg(EDI),ap1);                     
  1580.     gen_code(op_mov,4,makedreg(ECX),make_immed(node->size));  
  1581.     gen_code(op_cld,0,0,0);
  1582.     gen_code(op_rep,1,0,0);                                   
  1583.     gen_code(op_movsb,1,0,0);                                      
  1584.     if (regs[1])                                              
  1585.         gen_pop(ECX,am_dreg,0);
  1586.     gen_pop(EDI,am_dreg,0);
  1587.     gen_pop(ESI,am_dreg,0);
  1588.     freeop(ap2);
  1589.     freeop(ap1);
  1590.     release();
  1591.     return(ap2);
  1592. }
  1593. AMODE    *gen_assign(ENODE *node, int flags, int size)
  1594. /*
  1595.  *      generate code for an assignment node. if the size of the
  1596.  *      assignment destination is larger than the size passed then
  1597.  *      everything below this node will be evaluated with the
  1598.  *      assignment size.
  1599.  */
  1600. {       AMODE    *ap1, *ap2, *ap3,*ap4 = 0;
  1601.         int             ssize,rsize;
  1602.                 rsize = natural_size(node->v.p[1]);
  1603.         switch( node->v.p[0]->nodetype )
  1604.                 {
  1605.                                 case en_bits:
  1606.                                                 ssize = natural_size(node->v.p[0]);
  1607.                                                 break;
  1608.                 case en_ub_ref:
  1609.                                 case en_cub:
  1610.                         ssize = 1;
  1611.                         break;
  1612.                 case en_b_ref:
  1613.                                 case en_cb:
  1614.                         ssize = -1;
  1615.                         break;
  1616.                 case en_uw_ref:
  1617.                                 case en_cuw:
  1618.                         ssize = 2;
  1619.                         break;
  1620.                 case en_w_ref:
  1621.                                 case en_cw:
  1622.                         ssize = -2;
  1623.                         break;
  1624.                 case en_l_ref:
  1625.                                 case en_cl:
  1626.                                                 ssize = -4;
  1627.                                                 break;
  1628.                 case en_ul_ref:
  1629.                                 case en_cul:
  1630.                                 case en_cp:
  1631.                         ssize = 4;
  1632.                         break;
  1633.                 case en_tempref:
  1634.                 case en_regref:
  1635.                                                 ssize = node->v.p[0]->v.i >> 8;
  1636.                                                 break;
  1637.                                 case en_floatref:
  1638.                                 case en_cf:
  1639.                                                 ssize = 6;
  1640.                                                 break;
  1641.                                 case en_doubleref:
  1642.                                 case en_cd:
  1643.                                                 ssize = 8;
  1644.                                                 break;
  1645.                                 case en_longdoubleref:
  1646.                                 case en_cld:
  1647.                                                 ssize = 10;
  1648.                                                 break;
  1649.                                 default:
  1650.                                                 ssize = -4;
  1651.                 }
  1652.         if (chksize( ssize , rsize ))
  1653.                 rsize = ssize;
  1654.         ap2 = gen_expr(node->v.p[1],F_DREG | F_FREG | F_IMMED,rsize);
  1655.                 mark();
  1656.         ap1 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1657.                 if (!equal_address(ap1,ap2)    ) {
  1658.                     if (rsize > 4) {
  1659.                         floatstore(ap1,ssize,flags);
  1660.                         gen_codef(op_fwait,0,0,0);
  1661.                     }
  1662.                     else {
  1663.                         if (node->v.p[0]->nodetype == en_bits) {
  1664.                             bit_move(ap1,ap2,node->v.p[0],flags,ssize,rsize);
  1665.                         }
  1666.                         else {
  1667.                             if (ap2->mode != am_dreg && ap2->mode != am_immed
  1668.                                         && ap1->mode != am_dreg) {
  1669.                                 freeop(ap2);
  1670.                                 ap3 = temp_data();
  1671.                                 gen_code(op_mov,ssize,ap3,ap2);
  1672.                                 gen_code(op_mov,ssize,ap1,ap3);
  1673.                             }
  1674.                             else {
  1675.                         gen_code(op_mov,ssize,ap1,ap2);
  1676.                             }
  1677.                         }
  1678.                     }
  1679.                 }
  1680.                 release();
  1681.                 if (flags & F_NOVALUE)
  1682.                     freeop(ap2);
  1683.                 else {
  1684.                     do_extend(ap2,ssize,size,flags);
  1685.                     make_legal(ap2,flags,size);
  1686.                 }
  1687.         return ap2;
  1688. }
  1689. AMODE    *gen_refassign(ENODE *node, int flags, int size)
  1690. /*
  1691.  *      generate code for an assignment node. if the size of the
  1692.  *      assignment destination is larger than the size passed then
  1693.  *      everything below this node will be evaluated with the
  1694.  *      assignment size.
  1695.  */
  1696. {       AMODE    *ap1, *ap2, *ap3,*ap4;
  1697.         int             ssize,rsize;
  1698.                 rsize = natural_size(node->v.p[1]);
  1699.         switch( node->v.p[0]->nodetype )
  1700.                 {
  1701.                                 case en_bits:
  1702.                                                 ssize = natural_size(node->v.p[0]);
  1703.                                                 break;
  1704.                 case en_ub_ref:
  1705.                                 case en_cub:
  1706.                         ssize = 1;
  1707.                         break;
  1708.                 case en_b_ref:
  1709.                                 case en_cb:
  1710.                         ssize = -1;
  1711.                         break;
  1712.                 case en_uw_ref:
  1713.                                 case en_cuw:
  1714.                         ssize = 2;
  1715.                         break;
  1716.                 case en_w_ref:
  1717.                                 case en_cw:
  1718.                         ssize = -2;
  1719.                         break;
  1720.                 case en_l_ref:
  1721.                                 case en_cl:
  1722.                                                 ssize = -4;
  1723.                                                 break;
  1724.                 case en_ul_ref:
  1725.                                 case en_cul:
  1726.                                 case en_cp:
  1727.                         ssize = 4;
  1728.                         break;
  1729.                 case en_tempref:
  1730.                 case en_regref:
  1731.                                                 ssize = node->v.p[0]->v.i >> 8;
  1732.                                                 break;
  1733.                                 case en_floatref:
  1734.                                 case en_cf:
  1735.                                                 ssize = 6;
  1736.                                                 break;
  1737.                                 case en_doubleref:
  1738.                                 case en_cd:
  1739.                                                 ssize = 8;
  1740.                                                 break;
  1741.                                 case en_longdoubleref:
  1742.                                 case en_cld:
  1743.                                                 ssize = 10;
  1744.                                                 break;
  1745.                                 default:
  1746.                                                 ssize = -4;
  1747.                 }
  1748.         if (chksize( ssize , rsize ))
  1749.                 rsize = ssize;
  1750.         ap2 = gen_expr(node->v.p[1],F_DREG | F_FREG,rsize);
  1751.                 mark();
  1752.         ap1 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
  1753.                 ap4 = xalloc(sizeof(AMODE));
  1754.                 ap4->preg = ap1->preg;
  1755.                 ap4->mode = am_indisp;
  1756.                 ap4->offset = makenode(en_icon,0,0);
  1757.                 if (!equal_address(ap1,ap2)    )
  1758.                     if (rsize > 4) {
  1759.                         floatstore(ap4,ssize,flags);
  1760.                         gen_codef(op_fwait,0,0,0);
  1761.                     }
  1762.                     else
  1763.                         if (node->v.p[0]->nodetype == en_bits)
  1764.                             bit_move(ap4,ap2,node->v.p[0],flags,ssize,rsize);
  1765.                         else
  1766.                             if (ap2->mode != am_dreg && ap2->mode != am_immed
  1767.                                         && ap4->mode != am_dreg) {
  1768.                                 ap3 = temp_data();
  1769.                         gen_code(op_mov,rsize,ap3,ap2);
  1770.                         gen_code(op_mov,ssize,ap4,ap3);
  1771.                                 freeop(ap3);
  1772.                             }
  1773.                             else
  1774.                         gen_code(op_mov,ssize,ap4,ap2);
  1775.         freeop(ap1);
  1776.                 do_extend(ap2,ssize,size,flags);
  1777.                 make_legal(ap2,flags,size);
  1778.         return ap2;
  1779. }
  1780.  
  1781. AMODE    *gen_aincdec(ENODE *node, int flags, int size, int op)
  1782. /*
  1783.  *      generate an auto increment or decrement node. op should be
  1784.  *      either op_add (for increment) or op_sub (for decrement).
  1785.  */
  1786. {       AMODE    *ap1,*ap2;
  1787.         int             ssize,rsize;
  1788.         ssize = natural_size(node->v.p[0]);
  1789.                 if (!(flags & F_NOVALUE)) {
  1790.                     ap2 = temp_data();
  1791.                 }
  1792.                 mark();
  1793.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  1794.                 if (!(flags &F_NOVALUE)) {
  1795.                     gen_code(op_mov,ssize,ap2,ap1);
  1796.                 }
  1797.         gen_code(op,ssize,ap1,make_immed((int)node->v.p[1]));
  1798.                 freeop(ap1);
  1799.                 release();
  1800.                 if (!(flags & F_NOVALUE)) {
  1801.                     do_extend(ap2,ssize,size,flags);
  1802.                     make_legal(ap2,flags,size);
  1803.                 }
  1804.         return ap2;
  1805. }
  1806.  
  1807. int push_param(ENODE *ep, int size)
  1808. /*
  1809.  *      push the operand expression onto the stack.
  1810.  */
  1811. {       AMODE    *ap, *ap2;
  1812.                 int rv,sz;
  1813.                 switch (ep->nodetype) {
  1814.                                 case en_absacon:
  1815.                                                 ep->v.i = (( SYM *)ep->v.p[0])->value.i;
  1816.                         ap = xalloc(sizeof(AMODE));
  1817.                         ap->mode = am_immed;
  1818.                         ap->offset = ep;     /* use as constant node */
  1819.                         gen_code(op_push,4,ap,0);
  1820.                                                 rv = 4;
  1821.                                                 break;
  1822.                 case en_napccon:
  1823.                 case en_nacon:
  1824.                                                 ep->v.p[0] = ((SYM *)ep->v.p[0])->name;
  1825.                 case en_labcon:
  1826.                 case en_nalabcon:
  1827.                         ap = xalloc(sizeof(AMODE));
  1828.                         ap->mode = am_immed;
  1829.                         ap->offset = ep;     /* use as constant node */
  1830.                         gen_code(op_push,4,ap,0);
  1831.                         make_legal(ap,F_ALL,4);
  1832.                                                 rv = 4;
  1833.                                                 break;
  1834.                                 case en_cf:
  1835.                                 case en_floatref:
  1836.                                                 ap = gen_expr(ep,F_FREG | F_VOL,6);
  1837.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(4));
  1838.                                                 ap2 = make_immed(0);
  1839.                                                 ap2->preg = ESP;
  1840.                                                 ap2->mode = am_indisp;
  1841.                                                 gen_codef(op_fstp,6,ap2,0);
  1842.                                                 gen_codef(op_fwait,0,0,0);
  1843.                                                 rv = 4;
  1844.                                                 break;
  1845.                                 case en_cd:
  1846.                                 case en_doubleref:
  1847.                                                 ap = gen_expr(ep,F_FREG | F_VOL,8);
  1848.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(8));
  1849.                                                 ap2 = make_immed(0);
  1850.                                                 ap2->preg = ESP;
  1851.                                                 ap2->mode = am_indisp;
  1852.                                                 gen_codef(op_fstp,8,ap2,0);
  1853.                                                 gen_codef(op_fwait,0,0,0);
  1854.                                                 rv = 8;
  1855.                                                 break;
  1856.                                 case en_cld:
  1857.                                 case en_longdoubleref:
  1858.                                                 ap = gen_expr(ep,F_FREG | F_VOL,8);
  1859.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(10));
  1860.                                                 ap2 = make_immed(0);
  1861.                                                 ap2->preg = ESP;
  1862.                                                 ap2->mode = am_indisp;
  1863.                                                 gen_codef(op_fstp,10,ap2,0);
  1864.                                                 gen_codef(op_fwait,0,0,0);
  1865.                                                 rv = 8;
  1866.                                                 break;
  1867.                                 case en_rcon: 
  1868.                                 case en_fcon:
  1869.                                 case en_lrcon:
  1870.                                                 rv = size;
  1871.                                                 if (rv == 6) rv= 4;
  1872.                                                 if (rv == 10) rv= 12;
  1873.                                                 ap = gen_expr(ep,F_FREG | F_VOL,size);
  1874.                                                 make_floatconst(ap,size);
  1875.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(rv));
  1876.                                                 ap2 = make_immed(0);
  1877.                                                 ap2->preg = ESP;
  1878.                                                 ap2->mode = am_indisp;
  1879.                                                 gen_codef(op_fstp,rv,ap2,0);
  1880.                                                 gen_codef(op_fwait,0,0,0);
  1881.                                                 break;
  1882.                                 default:
  1883.                                                 rv = 4;
  1884.                                         ap = gen_expr(ep,F_ALL,4);
  1885.                                                 if (ap->mode != am_dreg &&ap->mode != am_immed&& ap->mode != am_freg) {
  1886.                                                     sz = natural_size(ep->v.p[0]);
  1887.                                                     if (sz < 4 && sz >-4) 
  1888.                                                         do_extend(ap,sz,4,F_DREG);
  1889.                                                 }
  1890.                                                 if (ap->mode == am_freg) {
  1891.                                                     gen_code(op_push,4,makedreg(3),0);
  1892.                                                     ap2 = make_immed(0);
  1893.                                                     ap2->preg = ESP;
  1894.                                                     ap2->mode = am_indisp;
  1895.                                                     gen_codef(op_fistp,4,ap2,0);
  1896.                                                     gen_codef(op_fwait,0,0,0);
  1897.                                                 }
  1898.                                                 else
  1899.                                                     gen_code(op_push,4,ap,0);
  1900.                                                 break;
  1901.                 }
  1902.         freeop(ap);
  1903.     stackdepth += rv;
  1904.     return(rv);
  1905. }
  1906. int push_stackblock(ENODE *ep)
  1907. {
  1908.     AMODE *ap;
  1909.     int sz = (ep->size + stackadd) &stackmod;
  1910.     if (!sz)
  1911.         return(0);
  1912.     gen_code(op_sub,4,makedreg(ESP),make_immed(sz));
  1913.     gen_code(op_push,4,makedreg(ESI),0);
  1914.     gen_code(op_push,4,makedreg(EDI),0);
  1915.     stackdepth+=sz+8;
  1916.     gen_code(op_lea,4,makedreg(EDI),make_stack(-8));
  1917.                 switch (ep->nodetype) {
  1918.                 case en_napccon:
  1919.                 case en_nacon:
  1920.                                                 ep->v.p[0] = ((SYM *)ep->v.p[0])->name;
  1921.                 case en_nalabcon:
  1922.                 case en_labcon:
  1923.                         ap = xalloc(sizeof(AMODE));
  1924.                         ap->mode = am_direct;
  1925.                         ap->offset = ep;     /* use as constant node */
  1926.                         gen_code(op_lea,4,makedreg(ESI),ap);
  1927.                                                 break;
  1928.                                 case en_absacon:
  1929.                                                 ep->v.i = (( SYM *)ep->v.p[0])->value.i;
  1930.                         ap = xalloc(sizeof(AMODE));
  1931.                         ap->mode = am_direct;
  1932.                         ap->offset = ep;     /* use as constant node */
  1933.                         gen_code(op_lea,4,makedreg(ESI),ap);
  1934.                                                 break;
  1935.                                 default:
  1936.                                         ap = gen_expr(ep,F_DREG | F_MEM | F_IMMED,4);
  1937.                                                 gen_code(op_mov,4,makedreg(ESI),ap);
  1938.                                                 break;
  1939.                 }
  1940.     gen_code(op_mov,4,makedreg(ECX),make_immed(sz));
  1941.     gen_code(op_cld,0,0,0);
  1942.     gen_code(op_rep,0,0,0);
  1943.     gen_code(op_movsb,0,0,0);
  1944.     gen_code(op_pop,4,makedreg(EDI),0);
  1945.     gen_code(op_pop,4,makedreg(ESI),0);
  1946.     stackdepth-=8;
  1947.     freeop(ap);
  1948.     return(sz);
  1949. }
  1950.  
  1951. int     gen_parms(ENODE *plist,int size)
  1952. /*
  1953.  *      push a list of parameters onto the stack and return the
  1954.  *      size of parameters pushed.
  1955.  */
  1956. {       int     i;
  1957.         i = 0;
  1958.         while( plist != 0 )
  1959.                 {             
  1960.                                 if (plist->nodetype == en_stackblock)
  1961.                                     i+=push_stackblock(plist->v.p[0]);
  1962.                                 else
  1963.                     i+=push_param(plist->v.p[0],size);
  1964.                 plist = plist->v.p[1];
  1965.                 }
  1966.         return i;
  1967. }
  1968.  
  1969. AMODE    *gen_fcall(ENODE *node,int flags, int size)
  1970. /*
  1971.  *      generate a function call node and return the address mode
  1972.  *      of the result.
  1973.  */
  1974. {       AMODE    *ap, *result;
  1975.                 ENODE *node2;
  1976.         int             i,ssize;
  1977.         result = temp_data();
  1978.         temp_data(); temp_data();       /* push any used data registers */
  1979.         freeop(result); freeop(result); freeop(result);
  1980.                 if (node->nodetype == en_callblock) {
  1981.                     i = gen_parms(node->v.p[1]->v.p[1]->v.p[1]->v.p[0],size);
  1982.               ap = gen_expr(node->v.p[0],F_ALL,4);
  1983.                     gen_code(op_push,4,ap,0);
  1984.                     i+=4;
  1985.                     stackdepth+=4;
  1986.                     node = node->v.p[1];
  1987.                     freeop(ap);
  1988.                     ssize = 4;
  1989.                 }
  1990.                 else {
  1991.             i = gen_parms(node->v.p[1]->v.p[1]->v.p[0],size);    /* generate parameters */
  1992.                     ssize = node->v.p[0]->v.i;
  1993.                 }
  1994.                 if (node->nodetype == en_intcall) {
  1995.                     AMODE *ap2 = xalloc(sizeof(AMODE));
  1996.                     ap2->mode = am_seg;
  1997.                     ap2->seg = e_cs;
  1998.                     gen_code(op_pushfd,0,0,0);
  1999.                     gen_code(op_push,0,ap2,0);
  2000.                 }
  2001.                                     
  2002.            if( node->v.p[1]->v.p[0]->nodetype == en_nacon || node->v.p[1]->v.p[0]->nodetype == en_napccon ) {
  2003.                                 SYM *sp= node->v.p[1]->v.p[0]->v.p[0];
  2004.                                 if (sp->inreg) {
  2005.                                     ap = makedreg(sp->value.i);
  2006.                                 }
  2007.                                 else {
  2008.                                     node->v.p[1]->v.p[0]->v.p[0] = sp->name;
  2009.                        ap = make_offset(node->v.p[1]->v.p[0]);
  2010.                                     ap->mode = am_immed;
  2011.                                 }
  2012.                    gen_code(op_call,0,ap,0);
  2013.                 }
  2014.            else
  2015.                    {
  2016.                                 if (node->v.p[1]->v.p[0]->nodetype == en_l_ref) {
  2017.                                     node2=node->v.p[1]->v.p[0]->v.p[0];
  2018.                                 }
  2019.                                 else {
  2020.                                     if (node->v.p[1]->v.p[0]->nodetype != en_tempref)
  2021.                                         DIAG("gen_fcall - questionable indirection");
  2022.                                     node2=node->v.p[1]->v.p[0];
  2023.                                 }
  2024.                    ap = gen_expr(node2,F_ALL,4);
  2025.                    freeop(ap);
  2026.                    gen_code(op_call,4,ap,0);
  2027.                 }
  2028.         if( i != 0 ) {
  2029.                                 if (i == 4)
  2030.                                     gen_code(op_pop,4,makedreg(ECX),0);
  2031.                                 else
  2032.                     gen_code(op_add,4,makedreg(4),make_immed(i));
  2033.                                 stackdepth -= i;
  2034.                 }
  2035.                 if (ssize > 4) {
  2036.                         result = fstack();
  2037.                 }
  2038.                 else {
  2039.           result = temp_data();
  2040.             if( result->preg != EAX)
  2041.                 gen_code(op_mov,4,result,makedreg(EAX));
  2042.                 }
  2043.                 result->tempflag = 1;
  2044.                 do_extend(result,ssize,size,flags);
  2045.                 make_legal(result,flags,size);
  2046.         return result;
  2047. }
  2048. AMODE    *gen_pfcall(ENODE *node,int flags, int size)
  2049. /*
  2050.  *      generate a function call node to a pascal function
  2051.  *            and return the address mode of the result.
  2052.  */
  2053. {       AMODE    *ap, *result;
  2054.         int             i,ssize;
  2055.                 ENODE * invnode = 0,*anode,*node2;
  2056.                 
  2057.                 /* invert the parameter list */
  2058.                 if (node->nodetype == en_pcallblock)
  2059.                     anode = node->v.p[1]->v.p[1]->v.p[1]->v.p[0];
  2060.                 else
  2061.                     anode = node->v.p[1]->v.p[1]->v.p[0];
  2062.                 while (anode) {
  2063.                     invnode = makenode(anode->nodetype,anode->v.p[0],invnode);
  2064.                     anode = anode->v.p[1];
  2065.                 }
  2066.         result = temp_data();
  2067.         temp_data(); temp_data();       /* push any used data registers */
  2068.         freeop(result); freeop(result); freeop(result);
  2069.                 if (node->nodetype == en_pcallblock) {
  2070.               ap = gen_expr(node->v.p[0],F_ALL,4);
  2071.                     gen_code(op_push,4,ap,0);
  2072.                     freeop(ap);
  2073.                     i=4;
  2074.                     stackdepth+=4;
  2075.                     i += gen_parms(invnode,size);
  2076.                     node = node->v.p[1];
  2077.                     ssize = 4;
  2078.                 }
  2079.                 else {
  2080.             i = gen_parms(invnode,size);    /* generate parameters */
  2081.                     ssize = node->v.p[0]->v.i;
  2082.                 }
  2083.                                     
  2084.            if( node->v.p[1]->v.p[0]->nodetype == en_nacon || node->v.p[1]->v.p[0]->nodetype == en_napccon ) {
  2085.                                 SYM *sp= node->v.p[1]->v.p[0]->v.p[0];
  2086.                                 if (sp->inreg) {
  2087.                                     ap = makedreg(sp->value.i);
  2088.                                 }
  2089.                                 else {
  2090.                                     node->v.p[0]->v.p[0]->v.p[0] = sp->name;
  2091.                        ap = make_offset(node->v.p[1]->v.p[0]);
  2092.                                     ap->mode = am_immed;
  2093.                                 }
  2094.                    gen_code(op_call,0,ap,0);
  2095.                 }
  2096.            else
  2097.                    {
  2098.                                 if (node->v.p[1]->v.p[0]->nodetype == en_l_ref) {
  2099.                                     node2=node->v.p[1]->v.p[0]->v.p[0];
  2100.                                 }
  2101.                                 else {
  2102.                                     if (node->v.p[1]->v.p[0]->nodetype != en_tempref)
  2103.                                         DIAG("gen_fcall - questionable indirection");
  2104.                                     node2=node->v.p[1]->v.p[0];
  2105.                                 }
  2106.                    ap = gen_expr(node2,F_ALL,4);
  2107.                    freeop(ap);
  2108.                    gen_code(op_call,4,ap,0);
  2109.                 }
  2110.                 stackdepth -= i;
  2111.                 if (ssize > 4) {
  2112.                         result = fstack();
  2113.                 }
  2114.                 else {
  2115.           result = temp_data();
  2116.             if( result->preg != EAX)
  2117.                 gen_code(op_mov,4,result,makedreg(EAX));
  2118.                 }
  2119.                 result->tempflag = 1;
  2120.                 do_extend(result,ssize,size,flags);
  2121.                 make_legal(result,flags,size);
  2122.         return result;
  2123. }
  2124.  
  2125. AMODE    *gen_expr(ENODE *node, int flags, int size)
  2126. /*
  2127.  *      general expression evaluation. returns the addressing mode
  2128.  *      of the result.
  2129.  */
  2130. {
  2131.                 AMODE    *ap1, *ap2;
  2132.         int             lab0, lab1;
  2133.         int             natsize;
  2134.         if( node == 0 )
  2135.                 {
  2136.                 DIAG("null node in gen_expr.");
  2137.                 return 0;
  2138.                 }
  2139.         switch( node->nodetype )
  2140.                 {
  2141.                                 case en_bits:
  2142.                                                 size = natural_size(node->v.p[0]);
  2143.                                                 ap1 = gen_expr(node->v.p[0],F_ALL,size);
  2144.                                                 if (!(flags & F_NOBIT))
  2145.                                                     bit_legal(ap1,node,size);
  2146.                                                 return ap1;
  2147.                                 case en_cb: 
  2148.                                 case en_cub:
  2149.                                 case en_cw: 
  2150.                                 case en_cuw:
  2151.                                 case en_cl: 
  2152.                                 case en_cul:
  2153.                                 case en_cf: 
  2154.                                 case en_cd: 
  2155.                                 case en_cld: 
  2156.                                 case en_cp:
  2157.                                                 ap1 = gen_expr(node->v.p[0],flags | F_MEM | F_DREG | F_FREG,natural_size(node->v.p[0]));
  2158.                                 do_extend(ap1,natural_size(node->v.p[0]),size,flags);
  2159.                                                 make_legal(ap1,flags,size);
  2160.                                                 return ap1;
  2161.                 case en_napccon:
  2162.                 case en_nacon:
  2163.                                                 node->v.p[0] = ((SYM *)node->v.p[0])->name;
  2164.                 case en_nalabcon:
  2165.                 case en_labcon:
  2166.                         ap1 = temp_data();
  2167.                                                 ap1->tempflag = TRUE;
  2168.                         ap2 = xalloc(sizeof(AMODE));
  2169.                         ap2->mode = am_direct;
  2170.                         ap2->offset = node;     /* use as constant node */
  2171.                         gen_code(op_lea,4,ap1,ap2);
  2172.                         make_legal(ap1,flags,size);
  2173.                         return ap1;             /* return reg */
  2174.                 case en_icon:
  2175.                                 case en_lcon: case en_lucon: case en_iucon: case en_ccon:
  2176.                                 case en_rcon: case en_lrcon: case en_fcon:
  2177.                         ap1 = xalloc(sizeof(AMODE));
  2178.                         ap1->mode = am_immed;
  2179.                         ap1->offset = node;
  2180.                         make_legal(ap1,flags,size);
  2181.                         return ap1;
  2182.                                 case en_absacon:
  2183.                                                 node->v.i = ((SYM *)node->v.p[0])->value.i;
  2184.                         ap1 = temp_data();
  2185.                                                 ap1->tempflag = TRUE;
  2186.                         ap2 = xalloc(sizeof(AMODE));
  2187.                         ap2->mode = am_direct;
  2188.                         ap2->offset = node;     /* use as constant node */
  2189.                         gen_code(op_lea,4,ap1,ap2);
  2190.                         make_legal(ap1,flags,size);
  2191.                         return ap1;             /* return reg */
  2192.                 case en_autocon:
  2193.                 case en_autoreg:
  2194.                         ap1 = temp_data();
  2195.                                                 ap1->tempflag = TRUE;
  2196.                         ap2 = xalloc(sizeof(AMODE));
  2197.                                 ap2->mode = am_indisp;
  2198.                                                 ap2->preg = ESP;
  2199.                                                 if (prm_linkreg) {
  2200.                                           ap2->preg = EBP;
  2201.                                           ap2->offset = makenode(en_icon,(char *)((SYM *)node->v.p[0])->value.i,0);
  2202.                                                 }
  2203.                                                 else if (((SYM *)node->v.p[0])->funcparm)
  2204.                                     ap2->offset = makenode(en_icon,(char *)(((SYM *)node->v.p[0])->value.i+framedepth+stackdepth),0);
  2205.                                 else
  2206.                                                     ap2->offset = makenode(en_icon,(char *)(((SYM *)node->v.p[0])->value.i+stackdepth+lc_maxauto),0);
  2207.                         gen_code(op_lea,4,ap1,ap2);
  2208.                         make_legal(ap1,flags,size);
  2209.                         return ap1;             /* return reg */
  2210.                 case en_b_ref:
  2211.                 case en_w_ref:
  2212.                 case en_ub_ref:
  2213.                 case en_uw_ref:
  2214.                 case en_l_ref:
  2215.                 case en_ul_ref:
  2216.                                 case en_floatref:
  2217.                                 case en_doubleref:
  2218.                                 case en_longdoubleref:
  2219.                         return gen_deref(node,flags,size);
  2220.                 case en_tempref:
  2221.                 case en_regref:
  2222.                         ap1 = xalloc(sizeof(AMODE));
  2223.                                                 ap1->tempflag = 0;
  2224.                         if( (node->v.i & 0xff) < 16 )
  2225.                                 {
  2226.                                 ap1->mode = am_dreg;
  2227.                                 ap1->preg = node->v.i & 0xff;
  2228.                                                                 ap1->tempflag = 1;
  2229.                                 }
  2230.                         else
  2231.                                                     if ((node->v.i &0xff) < 32)
  2232.                                 {
  2233.                                 ap1->mode = am_dreg;
  2234.                                 ap1->preg = (node->v.i & 0xff)- 12;
  2235.                                 }
  2236.                                                     else
  2237.                                 {
  2238.                                 ap1->mode = am_freg;
  2239.                                 ap1->preg = (node->v.i & 0xff) - 32;
  2240.                                 }
  2241.                         ap1->tempflag = 0;      /* not a temporary */
  2242.                                 do_extend(ap1,node->v.i >> 8,size,flags);
  2243.                         make_legal(ap1,flags,size);
  2244.                         return ap1;
  2245.                 case en_uminus:
  2246.                         return gen_unary(node,flags,size,op_neg, op_fchs);
  2247.                 case en_compl:
  2248.                         return gen_unary(node,flags,size,op_not, op_not);
  2249.                 case en_add:
  2250.                         return gen_binary(node,flags,size,op_add,op_fadd);
  2251.                 case en_sub:
  2252.                         return gen_binary(node,flags,size,op_sub,op_fsub);
  2253.                 case en_and:
  2254.                         return gen_binary(node,flags,size,op_and,op_and);
  2255.                 case en_or:
  2256.                         return gen_binary(node,flags,size,op_or,op_or);
  2257.                 case en_xor:
  2258.                         return gen_xbin(node,flags,size,op_xor,op_xor);
  2259.                                 case en_pmul:
  2260.                                                 return gen_pmul(node,flags,size);
  2261.                                 case en_pdiv:
  2262.                                                 return gen_pdiv(node,flags,size);
  2263.                 case en_mul:
  2264.                         return gen_mul(node,flags,size,op_imul);
  2265.                 case en_umul:
  2266.                         return gen_mul(node,flags,size,op_mul);
  2267.                 case en_div:
  2268.                         return gen_modiv(node,flags,size,op_idiv,0);
  2269.                 case en_udiv:
  2270.                         return gen_modiv(node,flags,size,op_div,0);
  2271.                 case en_mod:
  2272.                         return gen_modiv(node,flags,size,op_idiv,1);
  2273.                 case en_umod:
  2274.                         return gen_modiv(node,flags,size,op_div,1);
  2275.                 case en_alsh:
  2276.                         return gen_shift(node,flags,size,op_sal);
  2277.                 case en_arsh:
  2278.                         return gen_shift(node,flags,size,op_sar);
  2279.                 case en_lsh:
  2280.                         return gen_shift(node,flags,size,op_shl);
  2281.                 case en_rsh:
  2282.                         return gen_shift(node,flags,size,op_shr);
  2283.                 case en_asadd:
  2284.                         return gen_asadd(node,flags,size,op_add,op_fadd);
  2285.                 case en_assub:
  2286.                         return gen_asadd(node,flags,size,op_sub,op_fsub);
  2287.                 case en_asand:
  2288.                         return gen_aslogic(node,flags,size,op_and);
  2289.                 case en_asor:
  2290.                         return gen_aslogic(node,flags,size,op_or);
  2291.                 case en_asxor:
  2292.                         return gen_aslogic(node,flags,size,op_xor);
  2293.                 case en_aslsh:
  2294.                         return gen_asshift(node,flags,size,op_shl);
  2295.                 case en_asrsh:
  2296.                         return gen_asshift(node,flags,size,op_shr);
  2297.                 case en_asalsh:
  2298.                         return gen_asshift(node,flags,size,op_sal);
  2299.                 case en_asarsh:
  2300.                         return gen_asshift(node,flags,size,op_sar);
  2301.                 case en_asmul:
  2302.                         return gen_asmul(node,flags,size, op_imul);
  2303.                 case en_asumul:
  2304.                         return gen_asmul(node,flags,size,op_mul);
  2305.                 case en_asdiv:
  2306.                         return gen_asmodiv(node,flags,size,op_idiv,FALSE);
  2307.                 case en_asudiv:
  2308.                         return gen_asmodiv(node,flags,size,op_div,FALSE);
  2309.                 case en_asmod:
  2310.                         return gen_asmodiv(node,flags,size,op_idiv,TRUE);
  2311.                 case en_asumod:
  2312.                         return gen_asmodiv(node,flags,size,op_div,TRUE);
  2313.                 case en_assign:
  2314.                         return gen_assign(node,flags,size);
  2315.                 case en_refassign:
  2316.                         return gen_refassign(node,flags|F_NOVALUE,size);
  2317.                 case en_moveblock:
  2318.                         return gen_moveblock(node,flags,size);
  2319.                 case en_ainc:
  2320.                         return gen_aincdec(node,flags,size,op_add);
  2321.                 case en_adec:
  2322.                         return gen_aincdec(node,flags,size,op_sub);
  2323.                 case en_land:   case en_lor:
  2324.                 case en_eq:     case en_ne:
  2325.                 case en_lt:     case en_le:
  2326.                 case en_gt:     case en_ge:
  2327.                 case en_ult:    case en_ule:
  2328.                 case en_ugt:    case en_uge:
  2329.                 case en_not:
  2330.                         lab0 = nextlabel++;
  2331.                         lab1 = nextlabel++;
  2332.                         falsejp(node,lab0);
  2333.                         ap1 = temp_data();
  2334.                         gen_code(op_sub,4,ap1,ap1);
  2335.                         gen_code(op_inc,4,ap1,0);
  2336.                         gen_code(op_jmp,0,make_label(lab1),0);
  2337.                         gen_label(lab0);
  2338.                         gen_code(op_sub,4,ap1,ap1);
  2339.                         gen_label(lab1);
  2340.                         return ap1;
  2341.                 case en_cond:
  2342.                         return gen_hook(node,flags,size);
  2343.                 case en_void:
  2344.                         natsize = natural_size(node->v.p[0]);
  2345.                         freeop(gen_expr(node->v.p[0],F_ALL | F_NOVALUE,natsize));
  2346.                         return gen_expr(node->v.p[1],flags,size);
  2347.                                 case en_pfcall: case en_pfcallb:  case en_pcallblock:
  2348.                                                 return gen_pfcall(node,flags,size);
  2349.                 case en_fcall:  case en_callblock: case en_fcallb:
  2350.                 case en_trapcall:
  2351.                                 case en_intcall:
  2352.                         return gen_fcall(node,flags,size);
  2353.                 default:
  2354.                         DIAG("uncoded node in gen_expr.");
  2355.                         return 0;
  2356.                 }
  2357. }
  2358.  
  2359. int     natural_size(ENODE *node)
  2360. /*
  2361.  *      return the natural evaluation size of a node.
  2362.  */
  2363. {       int     siz0, ssize;
  2364.         if( node == 0 )
  2365.                 return 0;
  2366.         switch( node->nodetype )
  2367.                 {
  2368.                                 case en_absacon:
  2369.                                                 return stdaddrsize;
  2370.                                 case en_bits:
  2371.                                                 return 4;
  2372.                 case en_icon:
  2373.                                 case en_lcon: 
  2374.                                 case en_lucon: 
  2375.                                 case en_iucon: 
  2376.                                                 return 0;
  2377.                                 case en_ccon:                 
  2378.                                                 return 0;
  2379.                                 case en_rcon:
  2380.                                                 return 0;
  2381.                                 case en_doubleref:
  2382.                                                 return 8;
  2383.                                 case en_lrcon:
  2384.                                                 return 0;
  2385.                                 case en_longdoubleref:
  2386.                                                 return 10;
  2387.                                 case en_fcon:
  2388.                                                 return 0;
  2389.                                 case en_floatref:
  2390.                                                 return 6;
  2391.                                 case en_trapcall:
  2392.                 case en_labcon:
  2393.                 case en_nacon:  case en_autocon:  case en_autoreg:
  2394.                 case en_napccon: case en_nalabcon:
  2395.                                                 return stdaddrsize;
  2396.                                 case en_l_ref:
  2397.                                 case en_cl:
  2398.                                                 return -4;
  2399.                                 case en_pfcall: case en_pfcallb: 
  2400.                                 case en_fcall: case en_intcall: case en_callblock: case en_fcallb:
  2401.                                 case en_pcallblock:
  2402.                                                 return natural_size(node->v.p[1]);
  2403.                                 case en_tempref:
  2404.                                 case en_regref:
  2405.                                                 return node->v.i >> 8;
  2406.                 case en_ul_ref:
  2407.                                 case en_cul:
  2408.                         return 4;
  2409.                                 case en_cp:
  2410.                                                 return stdaddrsize;
  2411.                 case en_ub_ref:
  2412.                                 case en_cub:
  2413.                                                 return 1;
  2414.                 case en_b_ref:
  2415.                                 case en_cb:
  2416.                         return -1;
  2417.                 case en_uw_ref:
  2418.                                 case en_cuw:
  2419.                                                 return 2;
  2420.                 case en_cw:
  2421.                 case en_w_ref:
  2422.                         return -2;
  2423.                                 case en_cd:
  2424.                                                 return 8;
  2425.                                 case en_cld:
  2426.                                                 return stdldoublesize;
  2427.                                 case en_cf:
  2428.                                                 return 6;
  2429.                 case en_not:    case en_compl:
  2430.                 case en_uminus: case en_assign: case en_refassign:
  2431.                 case en_ainc:   case en_adec:
  2432.                                 case en_moveblock: case en_stackblock:
  2433.                         return natural_size(node->v.p[0]);
  2434.                 case en_add:    case en_sub:
  2435.                                 case en_umul:        case en_udiv:    case en_umod: case en_pmul:
  2436.                 case en_mul:    case en_div:  case en_pdiv:
  2437.                 case en_mod:    case en_and:
  2438.                 case en_or:     case en_xor:
  2439.                                 case en_asalsh: case en_asarsh: case en_alsh: case en_arsh:
  2440.                 case en_lsh:    case en_rsh:
  2441.                 case en_eq:     case en_ne:
  2442.                 case en_lt:     case en_le:
  2443.                 case en_gt:     case en_ge:
  2444.                                 case en_ugt: case en_uge: case en_ult: case en_ule:
  2445.                 case en_land:   case en_lor:
  2446.                 case en_asadd:  case en_assub:
  2447.                 case en_asmul:  case en_asdiv:
  2448.                 case en_asmod:  case en_asand:
  2449.                                 case en_asumod: case en_asudiv: case en_asumul:
  2450.                 case en_asor:   case en_aslsh:  case en_asxor:
  2451.                 case en_asrsh:
  2452.                         siz0 = natural_size(node->v.p[0]);
  2453.                         ssize = natural_size(node->v.p[1]);
  2454.                         if( chksize(ssize, siz0 ))
  2455.                                 return ssize;
  2456.                         else
  2457.                                 return siz0;
  2458.                 case en_void:   case en_cond:
  2459.                         return natural_size(node->v.p[1]);
  2460.                 default:
  2461.                         DIAG("natural size error.");
  2462.                         break;
  2463.                 }
  2464.         return 0;
  2465. }
  2466.  
  2467. void gen_compare(ENODE *node, int btype1, int btype2, int btype3, int btype4, int label)
  2468. /*
  2469.  *      generate code to do a comparison of the two operands of
  2470.  *      node.
  2471.  */
  2472. {       AMODE    *ap1, *ap2,  *ap3;
  2473.         int             size;
  2474.                 int btype = btype1;
  2475.                 ap3 = 0;
  2476.         size = natural_size(node);
  2477.                 if (size > 4) {
  2478.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL, size);
  2479.                     ap2 = gen_expr(node->v.p[1],F_ALL, size);
  2480.                     if (ap2->mode == am_freg) {
  2481.                         gen_codef(op_fcompp,0,0,0);
  2482.                     }
  2483.                     else
  2484.                         gen_codef(op_fcomp,size,ap2,0);
  2485.                     if (regs[0])
  2486.                         gen_push(EAX,am_dreg,0);
  2487.                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  2488.                     gen_codef(op_fwait,0,0,0);
  2489.                     gen_code(op_sahf,0,0,0);
  2490.                     if (regs[0])
  2491.                         gen_pop(EAX,am_dreg,0);
  2492.                     gen_branch(btype3,0,make_label(label));
  2493.                     return;
  2494.  
  2495.                 }
  2496.         ap1 = gen_expr(node->v.p[0],F_ALL,size);
  2497.                 mark();
  2498.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  2499.                 if (ap1->mode != am_dreg) {
  2500.                     if (ap2->mode == am_immed)  {
  2501.                         if (ap1->mode == am_immed)
  2502.                             goto cmp2;
  2503.                     }
  2504.                     else {
  2505.                         if (ap2->mode == am_dreg) {
  2506. swapit:
  2507.                             ap3 = ap2;
  2508.                             ap2 = ap1;
  2509.                             ap1 = ap3;
  2510.                             ap3 = 0;
  2511.                             btype = btype2;
  2512.                         }
  2513.                         else  
  2514.                             if (ap1->mode == am_immed) {
  2515.                                 goto swapit;
  2516.                             }
  2517.                             else {
  2518. cmp2:
  2519.                                 ap3 = ap1;
  2520.                   ap1 = temp_data();
  2521.                                 gen_code(op_mov,size,ap1,ap3);
  2522.                   make_legal(ap1,F_DREG,size);
  2523.                             }
  2524.                     }
  2525.                 }
  2526.                 if (ap1->mode == am_dreg && ap2->mode == am_immed && ap2->offset->v.i == 0)
  2527.             gen_code(op_or,size,ap1,ap1);
  2528.         else
  2529.                     gen_code(op_cmp,size,ap1,ap2);
  2530.                 release();
  2531.         gen_branch(btype,0,make_label(label));
  2532.                 if (ap3) {
  2533.                     freeop(ap1);
  2534.                     freeop(ap2);
  2535.                     freeop(ap3);
  2536.                 }
  2537.                 else {    
  2538.             freeop(ap2);
  2539.             freeop(ap1);
  2540.                 }
  2541. }
  2542.  
  2543. void truejp(ENODE *node, int label)
  2544. /*
  2545.  *      generate a jump to label if the node passed evaluates to
  2546.  *      a true condition.
  2547.  */
  2548. {       AMODE    *ap1;
  2549.         int             ssize;
  2550.         int             lab0;
  2551.         if( node == 0 )
  2552.                 return;
  2553.         switch( node->nodetype )
  2554.                 {
  2555.                 case en_eq:
  2556.                         gen_compare(node,op_je,op_je,op_je,op_je,label);
  2557.                         break;
  2558.                 case en_ne:
  2559.                         gen_compare(node,op_jne,op_jne,op_jne,op_jne,label);
  2560.                         break;
  2561.                 case en_lt:
  2562.                         gen_compare(node,op_jl,op_jg,op_jb,op_ja,label);
  2563.                         break;
  2564.                 case en_le:
  2565.                         gen_compare(node,op_jle,op_jge,op_jbe,op_jnc,label);
  2566.                         break;
  2567.                 case en_gt:
  2568.                         gen_compare(node,op_jg,op_jl,op_ja,op_jb,label);
  2569.                         break;
  2570.                 case en_ge:
  2571.                         gen_compare(node,op_jge,op_jle,op_jnc,op_jbe,label);
  2572.                         break;
  2573.                 case en_ult:
  2574.                         gen_compare(node,op_jb,op_ja,op_jb,op_ja,label);
  2575.                         break;
  2576.                 case en_ule:
  2577.                         gen_compare(node,op_jbe,op_jnc,op_jbe,op_jnc,label);
  2578.                         break;
  2579.                 case en_ugt:
  2580.                         gen_compare(node,op_ja,op_jb,op_ja,op_jb,label);
  2581.                         break;
  2582.                 case en_uge:
  2583.                         gen_compare(node,op_jnc,op_jbe,op_jnc,op_jbe,label);
  2584.                         break;
  2585.                 case en_land:
  2586.                         lab0 = nextlabel++;
  2587.                         falsejp(node->v.p[0],lab0);
  2588.                         truejp(node->v.p[1],label);
  2589.                         gen_label(lab0);
  2590.                         break;
  2591.                 case en_lor:
  2592.                         truejp(node->v.p[0],label);
  2593.                         truejp(node->v.p[1],label);
  2594.                         break;
  2595.                 case en_not:
  2596.                         falsejp(node->v.p[0],label);
  2597.                         break;
  2598.                 default:
  2599.                         ssize = natural_size(node);    
  2600.                                                 if (isintconst(node->nodetype)) {
  2601.                                                     if (node->v.i != 0) 
  2602.                                 gen_code(op_jmp,0,make_label(label),0);
  2603.                                                     break;
  2604.                                                 }
  2605.                                                 else
  2606.                                                     if (ssize > 4) {
  2607.                                                         ap1 = gen_expr(node,F_FREG | F_VOL, ssize);
  2608.                                                     }
  2609.                                                     else
  2610.                                 ap1 = gen_expr(node,F_ALL,ssize);
  2611.                                                 if (ssize > 4) {
  2612.                                                     gen_codef(op_fldz,0,0,0);
  2613.                                                     gen_codef(op_fcompp,0,0,0);
  2614.                                                     if (regs[0])
  2615.                                                         gen_push(EAX,am_dreg,0);
  2616.                                                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  2617.                                                     gen_codef(op_fwait,0,0,0);
  2618.                                                     gen_code(op_sahf,0,0,0);
  2619.                                                     if (regs[0])
  2620.                                                         gen_pop(EAX,am_dreg,0);
  2621.                                                 }
  2622.                                                 else {
  2623.                                                     if (ap1->mode == am_dreg) 
  2624.                                 gen_code(op_or,ssize,ap1,ap1);
  2625.                                                     else
  2626.                                 gen_code(op_test,ssize,ap1,make_immedt(0xffffffffL,ssize));
  2627.                             freeop(ap1);
  2628.                                                 }
  2629.                         gen_branch(op_jne,0,make_label(label));
  2630.                         break;
  2631.                 }
  2632. }
  2633.  
  2634. void falsejp(ENODE *node, int label)
  2635. /*
  2636.  *      generate code to execute a jump to label if the expression
  2637.  *      passed is false.
  2638.  */
  2639. {       AMODE    *ap1;
  2640.         int             ssize;
  2641.         int             lab0;
  2642.         if( node == 0 )
  2643.                 return;
  2644.         switch( node->nodetype )
  2645.                 {
  2646.                 case en_eq:
  2647.                         gen_compare(node,op_jne,op_jne,op_jne,op_jne,label);
  2648.                         break;
  2649.                 case en_ne:
  2650.                         gen_compare(node,op_je,op_je,op_je,op_je,label);
  2651.                         break;
  2652.                 case en_lt:
  2653.                         gen_compare(node,op_jge,op_jle,op_jnc,op_jbe,label);
  2654.                         break;
  2655.                 case en_le:
  2656.                         gen_compare(node,op_jg,op_jl,op_ja,op_jb,label);
  2657.                         break;
  2658.                 case en_gt:
  2659.                         gen_compare(node,op_jle,op_jge,op_jbe,op_jnc,label);
  2660.                         break;
  2661.                 case en_ge:
  2662.                         gen_compare(node,op_jl,op_jg,op_jb,op_ja,label);
  2663.                         break;
  2664.                 case en_ult:
  2665.                         gen_compare(node,op_jnc,op_jbe,op_jnc,op_jbe,label);
  2666.                         break;
  2667.                 case en_ule:
  2668.                         gen_compare(node,op_ja,op_jb,op_ja,op_jb,label);
  2669.                         break;
  2670.                 case en_ugt:
  2671.                         gen_compare(node,op_jbe,op_jnc,op_jbe,op_jnc,label);
  2672.                         break;
  2673.                 case en_uge:
  2674.                         gen_compare(node,op_jb,op_ja,op_jb,op_ja,label);
  2675.                         break;
  2676.                 case en_land:
  2677.                         falsejp(node->v.p[0],label);
  2678.                         falsejp(node->v.p[1],label);
  2679.                         break;
  2680.                 case en_lor:
  2681.                         lab0 = nextlabel++;
  2682.                         truejp(node->v.p[0],lab0);
  2683.                         falsejp(node->v.p[1],label);
  2684.                         gen_label(lab0);
  2685.                         break;
  2686.                 case en_not:
  2687.                         truejp(node->v.p[0],label);
  2688.                         break;
  2689.                 default:
  2690.                         ssize = natural_size(node);    
  2691.                                                 if (isintconst(node->nodetype)) {
  2692.                                                     if (node->v.i == 0) 
  2693.                                 gen_code(op_jmp,0,make_label(label),0);
  2694.                                                     break;
  2695.                                                 }
  2696.                                                 else
  2697.                                                     if (ssize > 4) {
  2698.                                                         ap1 = gen_expr(node,F_FREG | F_VOL, ssize);
  2699.                                                     }
  2700.                                                     else
  2701.                                 ap1 = gen_expr(node,F_ALL,ssize);
  2702.                                                 if (ssize > 4) {
  2703.                                                     gen_codef(op_fldz,0,0,0);
  2704.                                                     gen_codef(op_fcompp,0,0,0);
  2705.                                                     if (regs[0])
  2706.                                                         gen_push(EAX,am_dreg,0);
  2707.                                                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  2708.                                                     gen_codef(op_fwait,0,0,0);
  2709.                                                     gen_code(op_sahf,0,0,0);
  2710.                                                     if (regs[0])
  2711.                                                         gen_pop(EAX,am_dreg,0);
  2712.                                                 }
  2713.                                                 else {
  2714.                                                     if (ap1->mode == am_dreg) 
  2715.                                 gen_code(op_or,ssize,ap1,ap1);
  2716.                                                     else
  2717.                                 gen_code(op_test,ssize,ap1,make_immedt(0xffffffffL,ssize));
  2718.                             freeop(ap1);
  2719.                                                 }
  2720.                         gen_branch(op_je,0,make_label(label));
  2721.                         break;
  2722.                 }
  2723. }